Depurar una compilación de producción
Cómo abrir la consola en una aplicación empaquetada, dónde salen los mensajes de Rust cuando ya no hay terminal, y el plugin que junta las dos salidas en una sola línea de tiempo.
Las tres vías
La tercera es gratis y limitada: te da lo que el core imprima, y nada del frontend. Las dos primeras son las que resuelven de verdad, y las dos hay que haberlas previsto.
Abrir la consola en una compilación empaquetada
Dos formas, y conviene tener la segunda:
Activarlas al compilar. La feature correspondiente de Tauri deja las herramientas disponibles también en el perfil de publicación. A partir de ahí se abren como en cualquier navegador, con el atajo o el menú contextual, según la plataforma.
Abrirlas desde el código, bajo condición. Es la forma que más control da: dejar las herramientas compiladas y abrirlas solo cuando algo lo pida —una variable de entorno, un argumento de línea de comandos, un atajo escondido—.
// En setup: compiladas siempre, abiertas solo si alguien lo pide.#[cfg(feature = "devtools")]{ if std::env::var("MI_APP_DEVTOOLS").is_ok() { if let Some(w) = app.get_webview_window("main") { w.open_devtools(); } }}Con eso, la versión que publicas es igual para todo el mundo y quien necesite mirar dentro —tú, o un usuario al que se lo pidas— arranca con la variable puesta. Es el compromiso razonable entre soporte y superficie que el nivel 7.3 planteaba.
Los mensajes del core cuando no hay terminal
Un println! en una aplicación con doble clic no va a ninguna parte visible. La respuesta es el plugin de registro, que además hace algo más interesante que imprimir.
.plugin( tauri_plugin_log::Builder::new() .target(tauri_plugin_log::Target::new( tauri_plugin_log::TargetKind::LogDir { file_name: None }, )) .target(tauri_plugin_log::Target::new( tauri_plugin_log::TargetKind::Webview, )) .level(log::LevelFilter::Info) .build(),)Dos destinos, y el segundo es el que cambia las cosas:
- A fichero, en el directorio de registros de la aplicación, que es distinto en cada plataforma y el nivel 39 detalla. Es lo que le vas a pedir a un usuario que te mande.
- A la webview, que hace que los mensajes de Rust aparezcan en la consola del navegador, mezclados con los tuyos de JavaScript.
Una sola línea de tiempo
Ese segundo destino resuelve el problema real de depurar una aplicación con dos mitades: normalmente tienes los mensajes de Rust en un sitio y los del frontend en otro, sin forma de saber qué ocurrió antes.
Con el registro dirigido a la webview, la secuencia se lee de corrido:
[INFO] frontend: pidiendo el proyecto 42[INFO] core: cargar_proyecto(42)[WARN] core: el fichero no estaba en caché, leyendo de disco[INFO] core: 128 ficheros, 4.2 MB[ERROR] frontend: no se pudo pintar la lista: campo numeroFicheros indefinidoEse último mensaje, junto al anterior, señala el fallo en un segundo: el core devolvió los datos y el frontend esperaba otro nombre de campo. Con las dos salidas separadas, el mismo diagnóstico son diez minutos de ir y venir. Es el fallo del borde de tipos del nivel 4.5, y el nivel 19 lo elimina de raíz.
Qué dejar activo en lo que publicas
La decisión, con los tres elementos por separado:
| elemento | recomendación |
|---|---|
| Registro a fichero | siempre, con nivel informativo y rotación. Cuesta muy poco y salva el soporte |
| Registro a la webview | en desarrollo sí; en producción da igual, porque sin consola no se ve |
| Herramientas de desarrollo compiladas | sí, y abiertas solo bajo condición |
| Herramientas abiertas por defecto | no |
| Símbolos en el binario | quitarlos, pero guardarlos aparte si recoges informes de fallo. Nivel 10.2 |
La única que merece pensarse es la tercera, y el argumento a favor pesa: sin ella, un fallo que solo le pasa a un usuario concreto es prácticamente indiagnosticable. El argumento en contra —que alguien inspeccione tu interfaz— es real y limitado, porque el modelo de permisos sigue en pie: mirar la consola no concede ningún permiso que la capability no diera ya.