LogRock: Prueba a trav茅s del registro
Llevamos m谩s de 2 a帽os trabajando en nuestro proyecto
Cleverbrush . Este es un software para trabajar con gr谩ficos vectoriales. Trabajar con un editor gr谩fico implica una gran cantidad de casos de uso de aplicaciones. Estamos tratando de ahorrar dinero y tiempo, por lo que optimizamos todo, incluidas las pruebas. Cubrir los casos de prueba con cada opci贸n es demasiado costoso e irracional, especialmente porque es imposible cubrir todas las opciones.
Durante el desarrollo, se cre贸 un m贸dulo para aplicaciones React JS:
LogRock (github) .
Este m贸dulo le permite organizar aplicaciones modernas de registro. Seg煤n los registros, realizamos pruebas. En este art铆culo, le contar茅 sobre las complejidades del uso de este m贸dulo y c贸mo organizar las pruebas a trav茅s del registro.
Cual es el problema
Si compara el programa con un organismo vivo, entonces un error es una enfermedad. La causa de esta "enfermedad" puede ser una serie de factores, incluido el entorno de un usuario en particular. Esto es especialmente cierto si estamos considerando una plataforma web. A veces, una relaci贸n causal es muy compleja, y el error que se encontr贸 durante las pruebas es el resultado de una serie de eventos.
Al igual que con las enfermedades humanas, nadie explicar谩 sus s铆ntomas mejor que el paciente, ning煤n evaluador podr谩 decir lo que sucedi贸, mejor que el programa en s铆.
Que hacer
Para comprender lo que est谩 sucediendo, necesitamos una lista de acciones que el usuario realiz贸 en nuestra aplicaci贸n.
Para que nuestro programa mismo pueda decirnos qu茅 "duele", tomaremos el m贸dulo
LogRock (github) y lo asociaremos con ElasticSearch, LogStash y Kibana.
ElasticSearch es un poderoso motor de b煤squeda de texto completo. Puedes ver el tutorial de ElasticSearch
aqu铆 .
LogStash es un sistema para recopilar registros de varias fuentes, que pueden enviar registros, incluso a ElasticSearch.
Kibana es una interfaz web para ElasticSearch con muchos complementos.
Como funciona
En caso de un error (o solo a pedido), la aplicaci贸n env铆a registros al servidor donde se guardan en un archivo. Logstash guarda datos de forma incremental en ElasticSearch - en la base de datos. El usuario inicia sesi贸n en Kibana y ve los registros guardados.
Parece una Kibana bien sintonizada. Muestra datos de ElasticSearch. Kibana puede mostrar datos en forma de tablas, gr谩ficos, mapas, etc., lo cual es muy conveniente para analizar y comprender lo que est谩 sucediendo con nuestra aplicaci贸n.
隆En este art铆culo, NO discutir茅 la configuraci贸n de ElasticStack!Crear un sistema de registro
Como ejemplo, integraremos el sistema de registro en una aplicaci贸n JS de una p谩gina escrita en React. Realmente no importa en qu茅 marco se escribir谩 su aplicaci贸n. Tratar茅 de describir el enfoque de construir un sistema de registro en s铆 mismo.
1. Cliente
1.0 LogRock. Instalaci贸n
Enlace a LogRockPara instalar, debe realizar:
npm install logrock yarn add logrock
1.1 LogRock. Configuraci贸n de la aplicaci贸n
Para comenzar, envuelva nuestra aplicaci贸n en un componente
import { LoggerContainer } from "logrock"; <LoggerContainer> <App /> </LoggerContainer>
LoggerContainer es un componente que responde a los errores de su aplicaci贸n y forma una pila.
Una pila es un objeto con informaci贸n sobre el sistema operativo del usuario, el navegador, el bot贸n del mouse o del teclado que se presion贸 y, por supuesto, el subconjunto de acciones, donde se registran todas las acciones del usuario que realiz贸 en nuestro sistema.
LoggerContainer tiene varias configuraciones, considera algunas de ellas
<LoggerContainer active={true|false} limit={20} onError={stack => { sendToServer(stack); }} > <App /> </LoggerContainer>
activo: habilita o deshabilita el registrador
l铆mite: establece un l铆mite en el n煤mero de acciones recientes guardadas por el usuario. Si el usuario realiza 21 acciones, la primera de esta matriz se eliminar谩 autom谩ticamente. Por lo tanto, tendremos las 煤ltimas 20 acciones que precedieron al error.
onError: la devoluci贸n de llamada que se llama cuando se produce un error. El objeto Stack entra en 茅l, en el que se almacena toda la informaci贸n sobre el entorno, las acciones del usuario, etc. Es a partir de esta devoluci贸n de llamada que necesitamos enviar estos datos a ElasticSearch o al backend, o guardarlos en un archivo para su posterior an谩lisis y monitoreo.
1.2 LogRock. Registro
Para realizar un registro de alta calidad de las acciones del usuario, tendremos que cubrir nuestro c贸digo con llamadas de registro.
El m贸dulo LogRock viene con un registrador asociado con un LoggerContainer
Supongamos que tenemos un componente
import React, { useState } from "react"; export default function Toggle(props) { const [toggleState, setToggleState] = useState("off"); function toggle() { setToggleState(toggleState === "off" ? "on" : "off"); } return <div className={`switch ${toggleState}`} onClick={toggle} />; }
Para cubrirlo adecuadamente con un registro, debemos modificar el m茅todo de alternar
function toggle() { let state = toggleState === "off" ? "on" : "off"; logger.info(`React.Toggle|Toggle component changed state ${state}`); setToggleState(state); }
Hemos agregado un registrador en el que la informaci贸n se divide en 2 partes. React.Toggle nos muestra que esta acci贸n ocurri贸 en el nivel de React, el componente Toggle, y luego tenemos una explicaci贸n verbal de la acci贸n y el estado actual que lleg贸 a este componente. Tal separaci贸n en niveles no es necesaria, pero con este enfoque ser谩 m谩s claro d贸nde se ejecut贸 exactamente nuestro c贸digo.
Tambi茅n podemos usar el m茅todo "componentDidCatch", que se introdujo en React versi贸n 16, en caso de error.
2. Interacci贸n del servidor
Considere el siguiente ejemplo.
Supongamos que tenemos un m茅todo que recopila datos de usuario de un servidor. El m茅todo es as铆ncrono, parte de la l贸gica est谩 oculta en el backend. 驴C贸mo registrar este c贸digo correctamente?
En primer lugar, dado que tenemos una aplicaci贸n cliente, todas las solicitudes dirigidas al servidor pasar谩n por una 煤nica sesi贸n de usuario, sin volver a cargar la p谩gina. Para asociar acciones en el cliente con acciones en el servidor, debemos crear un SessionID global y agregarlo al encabezado de cada solicitud al servidor. En el servidor, podemos usar cualquier registrador que cubra nuestra l贸gica como un ejemplo de la interfaz y, en caso de error, env铆e estos datos con el ID de sesi贸n adjunto a Elastic a la placa de back-end.
1. Generamos SessionID en el cliente
window.SESSION_ID = `sessionid-${Math.random().toString(36).substr(3, 9)}`;
2. Debemos establecer el SessionID para todas las solicitudes al servidor. Si usamos bibliotecas para consultas, esto es muy simple declarando un SessionID para todas las consultas.
let fetch = axios.create({...}); fetch.defaults.headers.common.sessionId = window.SESSION_ID;
3. En LoggerContainer hay un campo especial para SessionID
<LoggerContainer active={true|false} sessionID={window.SESSION_ID} limit={20} onError={stack => { sendToServer(stack); }} > <App /> </LoggerContainer>
4. La solicitud en s铆 (en el cliente) se ver谩 as铆:
logger.info(`store.getData|User is ready for loading... User ID is ${id}`); getData('/api/v1/user', { id }) .then(userData => { logger.info(`store.getData|User have already loaded. User count is ${JSON.stringify(userData)}`); }) .catch(err => { logger.error(`store.getData|User loaded fail ${err.message}`); });
C贸mo funcionar谩 todo: registramos un registro, antes de la solicitud del cliente. Seg煤n nuestro c贸digo, vemos que ahora comenzar谩 la carga de datos del servidor. Adjuntamos un SessionID a la solicitud. Si nuestro backend est谩 cubierto de registros con la adici贸n de este SessionID y la solicitud falla, entonces podemos ver lo que sucedi贸 en el backend.
Por lo tanto, monitoreamos todo el ciclo de nuestra aplicaci贸n, no solo en el cliente, sino tambi茅n en el backend.
3. El probador
Trabajar con un probador merece una descripci贸n separada del proceso.
Como tenemos una startup, no tenemos requisitos formales y, a veces, no todo es l贸gico en el trabajo.
Si el probador no comprende el comportamiento, este es un caso que al menos debe considerarse. Adem谩s, a menudo, un probador simplemente no puede repetir una situaci贸n dos veces. Dado que los pasos que conducen a un comportamiento incorrecto pueden ser numerosos y no triviales. Adem谩s, no todos los errores conducen a consecuencias cr铆ticas, como la excepci贸n. Algunos de ellos solo pueden cambiar el comportamiento de la aplicaci贸n, pero el sistema no los puede interpretar como un error. Para estos fines, en la preparaci贸n, puede agregar un bot贸n en el encabezado de la aplicaci贸n para forzar el env铆o de registros. El probador ve que algo no est谩 funcionando bien, hace clic en el bot贸n y env铆a la Pila con acciones a ElasticSearch.
Sin embargo, si ha ocurrido un error cr铆tico, debemos bloquear la interfaz para que el probador no haga m谩s clic y no entre en un callej贸n sin salida.
Para estos fines, mostramos la pantalla azul de la muerte.
Vemos en la parte superior el texto con la Pila de este error cr铆tico, y debajo, las acciones que lo precedieron. Tambi茅n obtenemos el ID de error, es suficiente para que el probador lo seleccione y lo adjunte al ticket. M谩s tarde, este error se puede encontrar f谩cilmente en Kibana con esta ID.
Para estos fines, LoggerContainer tiene sus propias propiedades.
<LoggerContainer active={true|false} limit={20} bsodActive={true} bsod={BSOD} onError={stack => { sendToServer(stack); }} > <App /> </LoggerContainer>
bsodActive: activa / desactiva BSOD (la desactivaci贸n de BSOD se aplica al c贸digo de producci贸n)
bsod es un componente. Por defecto, se parece a la captura de pantalla anterior.
Para mostrar un bot贸n en un UI LoggerContainer, podemos usarlo en contexto
context.logger.onError(context.logger.getStackData());
4. LogRock. Interacci贸n del usuario
Puede enviar registros a la consola o mostr谩rselos al usuario, para esto debe usar el m茅todo stdout:
<LoggerContainer active={true|false} limit={20} bsodActive={true} bsod={BSOD} onError={stack => { sendToServer(stack); }} stdout={(level, message, important) => { console[level](message); if (important) { alert(message); } }} > <App /> </LoggerContainer>
stdout es un m茅todo responsable de mostrar mensajes.
Para hacer que el mensaje sea importante, es suficiente pasar el segundo par谩metro verdadero al registrador. Por lo tanto, este mensaje se puede mostrar al usuario en una ventana emergente, por ejemplo, si falla la carga de datos, podemos mostrar un mensaje de error.
logger.log('Something was wrong', true);
Registro avanzado
Si usa Redux, o soluciones similares con una Tienda, puede colocar un registrador en Middleware que procese sus Acciones, por lo tanto, todas las acciones importantes pasar谩n por nuestro sistema.
Para un registro efectivo, puede envolver sus datos en un objeto proxy y colocar registradores en todas las acciones con el objeto.
Para cubrir los m茅todos de terceros con el registro (m茅todos de biblioteca, m茅todos de c贸digo heredado), puede usar decoradores - "@".
Consejos
Registre aplicaciones, incluso en producci贸n, porque mejor que los usuarios reales, ning煤n probador encontrar谩 cuellos de botella.
No olvide indicar la recopilaci贸n de registros en el acuerdo de licencia.
隆NO registre contrase帽as, datos bancarios y otra informaci贸n personal!La redundancia de registros tambi茅n es mala, haga que las firmas sean lo m谩s claras posible.
Alternativas
Como enfoques alternativos, destaco:
- Rollbar es altamente personalizable. Le permite registrar 500 mil errores por $ 150 por mes. Recomiendo usarlo si est谩 desarrollando una aplicaci贸n desde cero.
- Sentry es m谩s f谩cil de integrar, pero menos personalizable. Le permite registrar 1 mill贸n de eventos por $ 200 por mes.
Ambos servicios le permiten hacer casi lo mismo e integrarse en el backend.
Que sigue
El registro no es solo la b煤squeda de errores, sino que tambi茅n supervisa las acciones del usuario y la recopilaci贸n de datos. El registro puede ser un buen complemento para las pruebas de Google Analytics y la experiencia del usuario.
Conclusiones
Cuando liberas la aplicaci贸n, la vida apenas comienza para 茅l. Sea responsable de su creaci贸n, obtenga comentarios, monitoree los registros y mej贸relos. Escriba software de alta calidad y prospere :)
PD Si quieres ayudar con el desarrollo de m贸dulos para Angular, Vue, etc. Estar茅 encantado de recibir solicitudes
aqu铆 .