# Guión charla Debugging & Profiling
TODO definir lo que es texto del guión y lo que quiero poner en el slide
## Presentación
Somos Alberto Menéndez y, quien les habla, Fernando Canizo y hoy les venimos a
hablar de debugging y profiling en Nodejs.
## Debugging?
El debugging, o despioje o depuración de programas es el proceso de identificar
y corregir errores de programación.
Se dice que el nombre nació debido a que en 1947 encontraron una polilla en la
computadora Mark II, y ésta estaba ocasionando errores en los cálculos. Una
polilla es un bicho, en inglés bicho es "bug", por lo tanto quitar bugs es
_debugging_.
## Estadísticas
[Statista](https://www.statista.com/) es una empresa dedicada a las estadísticas
en Estados Unidos, te hacen estadísticas de lo que se te ocurra. Una empresa muy
respetada por allá.
Encontramos este gráfico en su sitio, que muestra que el debugging y el testeo
manual es la segunda acción más ejecutada en el software después de escribirlo,
que es lo que toma el mayor tiempo.
Dejemos que cale un poco esta información: primero escribimos el software, y eso
nos toma el 30% del tiempo, y luego buscamos y resolvemos errores, usando un 17%
del tiempo, poco más de la mitad. Y después vienen el resto de las tareas
relacionadas con la producción, despliegue y mantenimiento del software.
No es una tarea menor y por lo tanto debemos aprender a hacerla bien.
## Rubberduck
La primer forma de debugging es el debugging mental. Esclarecer las ideas, las
preguntas que nos queremos hacer primero en nuestra mente. Para eso se usa la
técnica del _rubberducking_.
Les voy a contar una anécdota: en mi laburo anterior el equipo era chico y
trabajábamos todos en una misma sala. Entonces no costaba nada darse vuelta y
molestar a un compañero para pedirle una opinión.
La necesidad de explicar tu problema en voz alta hace que necesariamente ordenes
tus ideas. Y al ordenarlas, muchas veces aclarás tanto el panorama que terminás
respondiendo tu pregunta inicial vos mismo.
### `console.log()` y amigos
Cuando hablamos de debugging quizá lo primero que se nos viene a la cabeza es
usar el debugger de Nodejs, del que seguramente hemos escuchado en algún momento
de nuestras carreras, e incluso tal vez hasta lo hayamos usado ya, sin embargo
lo primero que efectivamente la mayoría hace, es llenar de `console.log` el
código.
Y no está mal. Nosotros les vamos a mostrar en un rato cómo usar el debugger de
Nodejs, pero también es cierto que un desarrollador debe tener criterio, y si no
lo tiene aún, lo debe ir educando mediante la experiencia.
Si tenés que ver el estado de muchas variables complejas (un JSON gigante), si
acaso tenés un flujo de llamadas entre funciones relativamente elaborado,
también complejo, entonces quizá usar `console.log` no sea lo más recomendable.
Sin embargo si, por ejemplo, estás debuggeando una REST API livianita, ordenada,
donde conocés el flujo al dedillo y sabés aproximadamente donde tenés que buscar
un problema en particular, entonces tirar un par de `console.log` puede
resultarte mucho más sencillo que levantar el debugger, setear breakpoints y
watchers para llegar adonde querés y observar el estado de las variables que te
interesan.
No hay una medida, esto lo define el criterio de cada uno.
- .clear -> limpia la pantalla
- .log = .debug = .info -> alias cuya utilidad podría ser que sean fáciles de
encontrar para eliminar al terminar de debuggear
- .error = .warn -> imprimen a standard error, que en general lo tenemos
apuntando a stdout también, así que podría decirse que su utilidad es la misma
que los anteriores
Personalmente uso uno solo: .log si ya tengo un logger distinto. O .log y
.debug si no estoy usando otro logger.
- .dir -> permite imprimir objetos complejos con la profundidad que deseemos
- .table -> imprime objetos complejos en tablita bonita
- .trace -> imprime stack trace como el de una exepción
### Otros loggers
En todo proyecto se suelen usar bibliotecas especializadas para hacer logging
debido a diferentes razones: performance, colorcitos u otros formateos bonitos,
manejo de la permanencia y en particular quiero hablarles de los niveles, la
mayoría implementa más o menos los mismos niveles, que son los de `npm`:
```
{
error: 0,
warn: 1,
info: 2,
http: 3,
verbose: 4,
debug: 5,
silly: 6
}
```
Dado que estos niveles son configurables, nosotros podemos agregar otros que nos
interesen si lo necesitamos.
Una cosa que suelo hacer en los proyectos que me lo permiten, es loggear el
flujo y las queries. Pero lo configuro en niveles especiales y de baja
prioridad, de manera que no molesten en general. Por ejemplo, podría modificar
los niveles anteriores de la siguiente manera:
```
{
// ... todo igual hasta 'debug'
flux: 6,
query: 7,
silly: 8,
}
```
De esta manera yo puedo usar la convención de colocar un log al inicio de cada
función:
```
const foo = () => {
log.flux('foo');
// ... the rest of the function code
};
```
Y luego si deseo ver por donde se movió un request de principio a fin, puedo
activar ese nivel llamando a mi programa con `LOG_LEVEL=flux node app.js`.
Idem para queries. Y a veces uso el nivel `silly` cuando tengo que tirar a
consola una variable gigante que sé que va a escupir varias páginas de
información.
De esta manera podemos dejar estas sentencias de logueo en el código y
activarlas cuando necesitamos debuguear.
### `at()`
Un problema que me suelo encontrar cuando uso estas técnicas manuales es que uno
pone varias sentencias de log y en un momento, tenés que comenzar a
identificarlas. Entonces escribís cosas como:
```
log.debug('antes del if');
log.debug('en if');
log.debug('en else');
log.debug('antes de llamar a foo');
log.debug('>>>>>>>>>>>>>>>>>>>', someVariableWeWantToInspect);
```
Entonces, y un poco también de la mano de esta técnica de tener todo
pre-logueado y activarlo cuando se requiere, suelo usar un modulito de mi propia
cosecha que llamé `at`.
Lo que hace `at` es generar una excepción y parsearla para extraer de la misma
el archivo y línea donde se llamó a `at`. De esa manera podemos configurar
nuestro logger o al mismo `console.log` para que llamen a `at` y de esta manera
nos evitamos tener que agregar comentarios de texto para poder identificar las
distintas llamadas.
Luego, mi código solo hace:
```
log();
log();
log({ someVariableWeWantToInspect });
```
### Paquete `debug`
Un paquete especialmente interesante para imprimir en consola es `debug`. La
diferencia que tiene este paquete respecto de los loggers con niveles, es que
`debug` permite definir cadenas de texto en tu código, de manera que la
impresión de las sentencias de debugging de dicho módulo solo se ejecuten de
acuerdo a la configuración de la variable de ambiente `DEBUG`.
Por ejemplo, ustedes podrían tener el módulo A y el B, cada uno con una cadena
configurada y llamadas a debug, luego pueden iniciar su aplicación de varias
maneras para ver todo el debugging, o solo el que les interese, ejemplos:
```
DEBUG='myapp:*' # muestra todo
DEBUG='myapp:a' # solo mostrará las sentencias del módulo 'a'
DEBUG='myapp:b' # solo mostrará las sentencias de debugging del módulo 'b'
```
Lo interesante del paquete `debug` es que muchas librerías lo usan. Entonces
cuando necesitan ir a ver más allá de su código, qué está ocurriendo con la
aplicación, eso suele estar disponible en muchos paquetes.
### Node inspector
- Muestro el código
- Muestro el código corriendo hasta que explote. Pero no sabemos qué se rompió.
- Primera opción: lo que ya aprendimos antes: log, log, log, antes de cada
llamada para saber cuál explota. Cada log debe tener un identificador si no
estamos usando `at()`, y si no hay que escribir los distintos logs con
mensajes que nos indiquen donde estamos. -> Mostrar una versión del código con
logs con distintos mensajitos. Pero solo mostrarla y señalar que podemos usar
el debugger de Nodejs.
Debugger legacy para CLI
- help para ver comandos
- step o next
- repl para revisar variables, CTRL-C para salir del REPL
Muestro esta version y muestro como examinar variables entrando al `repl`.
Cortita.
Hacer notar que este debugger hace un break automáticamente en la primera línea
de código. También podemos colocar la palabra reservada `debugger` en el código
y el debugger se detendrá en esa línea. Es una manera de poner un
hard-breakpoint.
- Entonces corro node --inspect -> señalar como el programa termina y no pude
revisar nada => entonces necesitamos `--inspect-brk`
Mencionar que puede ser que les pida permiso para acceder los archivos del
disco la primera vez.
- Correr con `--inspect-brk`
- Recorrer el programa y mostrar y comentar las distintas funciones y hotkeys:
- Step: F9
- Step over: F10
- Step out: Shift F11 (para cuando nos metemos en código que no nos interesa
revisar: bibliotecas y funciones internas de Nodejs)
- Continuar: F8
Esto puede ser útil para dejar correr el resto del script en busca de algún
resultado final, o bien, para parar en un siguiente breakpoint que hayamos
definido en el debugger. -> Mostrar cómo se ponen breakpoints y watchers.
#### Debugging remoto (mención)
Es posible debuggear remotamente una aplicación, incluso podría ser una
aplicación en pro.
https://nodejs.org/en/docs/guides/debugging-getting-started/#enabling-remote-debugging-scenarios
### `nodemon`
### Pasada a Alberto haciendo lo mismo en VSCode