Debugging
Técnicas y herramientas para depurar código en cualquier VAPP el ejmplo utiliza vasak-desktop con el fin de tener un caso de uso amplio.
Debugging del Frontend (Vue.js / TypeScript)
1. Herramientas de Desarrollo del Navegador
Abrir DevTools:
1
|
F12 o Ctrl+Shift+I o Cmd+Option+I
|
Pestañas principales:
- Console: Ver logs y errores
- Elements: Inspeccionar DOM
- Network: Ver requests
- Sources: Debugger paso a paso
- Vue DevTools: Extensión Vue.js
2. Console Logging
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
|
// Logs normales
console.log('Volumen:', volume);
// Información
console.info('Operación completada');
// Warnings
console.warn('Valores inusuales detectados');
// Errores
console.error('Ocurrió un error:', error);
// Grupar logs relacionados
console.group('Audio Settings');
console.log('Volumen:', volume);
console.log('Dispositivo:', device);
console.groupEnd();
// Tabla de datos
console.table([
{ name: 'Device 1', volume: 50 },
{ name: 'Device 2', volume: 75 }
]);
// Timing
console.time('loadAudio');
loadAudio();
console.timeEnd('loadAudio');
|
3. Debugger Paso a Paso
En Sources tab de DevTools:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
|
// Breakpoint condicional
function updateVolume(newVolume) {
// Haz click derecho en número de línea
// Elige "Add conditional breakpoint"
// Condición: newVolume < 0 || newVolume > 100
this.volume = newVolume;
}
// Dentro de DevTools, puedes:
// - Avanzar línea (F10)
// - Entrar en función (F11)
// - Salir de función (Shift+F11)
// - Ver variables locales
// - Ejecutar comandos en console mientras parado
|
Extensión para depurar Vue:
1
2
3
4
5
6
|
1. Instala: https://devtools.vuejs.org/
2. Abre DevTools (F12)
3. Ve a pestaña "Vue"
4. Inspecciona componentes
5. Modifica datos en tiempo real
6. Ve eventos emitidos
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
|
// Crear función de log personalizada
const log = {
audio: (msg: string, data?: any) => {
console.log(`[AUDIO] ${msg}`, data || '');
},
network: (msg: string, data?: any) => {
console.log(`[NETWORK] ${msg}`, data || '');
},
bluetooth: (msg: string, data?: any) => {
console.log(`[BT] ${msg}`, data || '');
},
};
// Uso
log.audio('Volumen cambió a:', 50);
log.network('WiFi conectado a:', 'MyNetwork');
|
Debugging del Backend (Rust)
1. Print Debugging
1
2
3
4
5
6
7
8
9
10
11
|
// Log simple
println!("Volumen: {}", volume);
// Debug format
println!("Struct: {:?}", device);
// Pretty print
println!("Struct: {:#?}", device);
// Con eprint para stderr
eprintln!("Error: {}", error);
|
2. Macros de Debug
1
2
3
4
5
6
7
8
|
// dbg! macro
let volume = dbg!(get_volume()); // Imprime valor y lo retorna
// assert!/assert_eq!
assert_eq!(volume, 50, "Volume debería ser 50");
// debug_assert!
debug_assert!(volume <= 100, "Volume fuera de rango");
|
3. Variables de Entorno para Logging
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
|
# Mostrar todos los logs
RUST_LOG=debug cargo run
# Solo módulo específico
RUST_LOG=vasak_desktop::audio=debug cargo run
# Nivel TRACE (muy verboso)
RUST_LOG=trace cargo run
# Múltiples módulos
RUST_LOG=vasak_desktop::audio=debug,vasak_desktop::network=info cargo run
# Backtrace en panics
RUST_BACKTRACE=1 cargo run
RUST_BACKTRACE=full cargo run
|
4. Log Macros (si uses log crate)
1
2
3
4
5
6
|
use log::{debug, info, warn, error};
debug!("Debug message: {:?}", data);
info!("Information message");
warn!("Warning message");
error!("Error message");
|
5. Debugger GDB/LLDB
1
2
3
4
5
6
7
8
9
10
11
|
# Ejecutar con debugger (Linux)
lldb target/debug/vasak-desktop
# En el prompt:
# (lldb) b main # Breakpoint en main
# (lldb) r # Run
# (lldb) c # Continue
# (lldb) n # Next line
# (lldb) s # Step into function
# (lldb) p variable_name # Print variable
# (lldb) q # Quit
|
Debugging de IPC (Frontend ↔ Backend)
1. Ver Comandos IPC
Frontend:
1
2
3
4
5
6
7
|
// Antes de llamar comando
console.log('Llamando:', 'set_volume', { level: 50 });
// En la llamada
const result = await invoke('set_volume', { level: 50 });
console.log('Resultado:', result);
|
Backend:
1
2
3
4
5
|
#[tauri::command]
pub fn set_volume(level: u32) -> Result<(), String> {
eprintln!("📡 IPC set_volume llamado con level: {}", level);
// implementación
}
|
2. Tauri Debug Info
1
2
3
4
5
6
7
|
# Ver información de Tauri
cargo tauri info
# Salida:
# Platform: Linux
# Tauri version: 2.8.0
# Node.js version: v20.0.0
|
Debugging de D-Bus
1. Monitor D-Bus
1
2
3
4
5
6
7
8
9
|
# Ver todos los mensajes D-Bus
dbus-monitor --session
# Filtrar por interfaz
dbus-monitor --session \
"interface='org.pulseaudio.Server'"
# Filtrar solo señales
dbus-monitor --session type='signal'
|
2. Llamar D-Bus desde CLI
1
2
3
4
5
6
7
8
9
10
|
# Llamar método
dbus-send --session --print-reply \
/org/pulseaudio/core1 \
org.PulseAudio.Core1.GetVolume
# Ver propiedades
busctl --user get-property \
org.freedesktop.NetworkManager \
/org/freedesktop/NetworkManager \
State
|
3. Logs de D-Bus en Rust
1
2
3
4
5
6
7
|
// Habilitar logging de zbus
env_logger::Builder::from_default_env()
.format_timestamp_millis()
.init();
// Luego ejecutar con:
RUST_LOG=zbus=debug cargo run
|
Debugging de Rendering
1. Inspeccionar DOM
1
2
3
4
5
6
7
8
9
10
|
// En console
document.querySelector('.panel');
document.querySelectorAll('.btn');
// Modificar estilos
document.querySelector('.panel').style.background = 'red';
// Ver eventos registrados
monitorEvents(element, 'click');
unmonitorEvents(element);
|
1
2
3
4
5
6
7
8
|
// En console
performance.mark('start-operation');
// ... hacer algo ...
performance.mark('end-operation');
performance.measure('operation', 'start-operation', 'end-operation');
performance.getEntriesByName('operation');
|
3. Vue Component Hierarchy
Con Vue DevTools:
- Abre DevTools
- Ve a pestaña “Vue”
- Expande árbol de componentes
- Haz click en componente para ver props y estado
- Modifica datos en tiempo real
1. Frontend
1
2
3
4
5
6
7
8
9
10
|
// Medir tiempo de render
console.time('render');
// ... operación ...
console.timeEnd('render');
// Timeline de Vue
import { useRenderTracking } from '@vueuse/core';
// En DevTools > Performance tab
// Graba sesión y analiza flamegraph
|
2. Backend
1
2
3
4
5
6
7
8
9
|
# Compilar con optimizaciones de debug
RUSTFLAGS="-C debuginfo=full" cargo build
# Ver tiempos de compilación
cargo build -Z timings
# Profiler (Linux)
perf record -F 99 ./target/debug/vasak-desktop
perf report
|
Debugging de Async/Await
1. Promesas en Frontend
1
2
3
4
5
6
7
8
9
10
11
12
13
|
// Ver estado de promesa
const promise = invoke('get_volume');
console.log(promise); // Ver en console qué hace
// Usar async/await
async function checkVolume() {
try {
const volume = await invoke('get_volume');
console.log('Volume:', volume);
} catch (error) {
console.error('Error:', error);
}
}
|
2. Async en Rust
1
2
3
4
5
6
7
8
9
10
11
|
// Con logs
#[tauri::command]
pub async fn get_device() -> Result<Device> {
eprintln!("🔄 Iniciando get_device");
// Simular async work
tokio::time::sleep(Duration::from_secs(1)).await;
eprintln!("✓ Completado get_device");
Ok(device)
}
|
Debugging de Memory Leaks
1. Frontend
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
|
// En DevTools > Memory tab
// 1. Toma un heap snapshot
// 2. Realiza operación que crees tiene leak
// 3. Toma otro heap snapshot
// 4. Compara las dos
// Para debug manual
let listeners = [];
// ❌ Memory leak - listeners nunca se limpian
element.addEventListener('click', handler);
listeners.push(handler);
// ✅ Correcto - limpiar en unmount
onUnmounted(() => {
listeners.forEach(h => element.removeEventListener('click', h));
});
|
2. Backend
1
2
3
4
5
|
# Usar valgrind (Linux)
valgrind --leak-check=full ./target/debug/vasak-desktop
# Usar perf para memory
perf record -e cache-misses ./target/debug/vasak-desktop
|
Debugging de Threads
1. Rust Threads
1
2
3
4
5
6
7
8
9
|
use std::thread;
let handle = thread::spawn(|| {
eprintln!("🧵 Thread: {:?}", thread::current().id());
// trabajo
});
eprintln!("🧵 Main: {:?}", thread::current().id());
handle.join().unwrap();
|
2. Tokio Tasks
1
2
3
4
5
6
7
8
9
10
11
12
|
#[tokio::main]
async fn main() {
eprintln!("📋 Task iniciada");
let task = tokio::spawn(async {
eprintln!("📋 Tarea ejecutándose");
// trabajo async
});
task.await.unwrap();
eprintln!("📋 Task completada");
}
|