debugging - plugin - tag assistant
"Funciona en mi máquina": ¿cómo solucionar errores no reproducibles? (22)
Aún no se ha mencionado, pero la "revisión del código dirigido" es una buena solución, especialmente si no realizó una revisión adecuada (al menos 1 hora por cada 100 líneas de código) antes de la publicación.
También he visto demostraciones impresionantes de AppSight Suite, que es básicamente una herramienta avanzada de monitoreo y registro del entorno. Le permite al cliente registrar lo que sucede en su máquina en un archivo de registro extenso pero bastante compacto que luego puede reproducir.
Muy ocasionalmente, a pesar de todos los esfuerzos de prueba, recibo un informe de error de un cliente que simplemente no puedo reproducir en la oficina.
( Disculpas a Jeff por el ''préstamo'' de la insignia)
Tengo algunas "herramientas" que puedo usar para tratar de localizarlas y arreglarlas, pero siempre se siente como si fuera un bisturí:
- Pidiendo cada vez más contexto al cliente: (systeminfo)
- Archivos de registro de nuestra aplicación
- Pruebas ad-hoc con el cliente para intentar cambiar el comportamiento
- Proporcionar al cliente una nueva compilación con diagnósticos adicionales
- Pensando en el problema en el baño ...
- Visita al sitio (suponiendo que el cliente esté en algún lugar cálido y soleado)
¿Existen procedimientos establecidos u otras técnicas que nadie usa para resolver problemas como este?
Como ingeniero de software que trabaja en la web (sistemas de reservas / compras / miembros, etc.), lo más importante para nosotros es obtener la mayor información posible del cliente.
Ir desde
¡está roto!
a
¡está roto! y aquí hay capturas de pantalla de cada opción que elegí mientras generaba este informe en particular
Reduce la cantidad de tiempo que nos lleva reproducir y solucionar un problema sin fin.
Puede ser obvio, pero a veces se necesita una gran cantidad de persecución para obtener este tipo de información de nuestros clientes. Pero vale la pena solo por esos momentos en los que descubres que en realidad no están haciendo lo que dicen que son.
Como muchos han mencionado, el registro extenso y pedirle al cliente los archivos de registro cuando algo sale mal. Además, a medida que trabajé más con aplicaciones web, también proporcionaré documentación de implementación detallada pero sucinta (por ejemplo, pasos de implementación, recursos ambientales que deben configurarse, etc.).
Aquí hay problemas comunes que he visto que conducen a los tipos de problema que está describiendo:
- El entorno no está configurado correctamente (p. Ej., Variables de entorno faltantes, fuentes de datos, etc.).
- Aplicación no completamente implementada (p. Ej., Esquema de base de datos no implementado).
- Diferencia en la configuración del sistema operativo (la codificación de caracteres predeterminada es el culpable más común para mí).
La mayoría de las veces, estos problemas se pueden identificar a través del contenido del registro.
Creo que seguir el rastro de las acciones que el usuario tomó puede llevarnos a los motivos de falla o fallas selectivas. Pero la mayoría de las veces los usuarios no saben describir con precisión las interacciones con las aplicaciones, la captura de pantalla automática (si se trata de una aplicación de escritorio para la aplicación .net, puede consultar el UnhandledExceptionHandler de Jeff). Registrar todas las acciones importantes que cambian el estado de los objetos también puede ayudarnos a comprenderlo.
Creo que una de las cosas más importantes es la capacidad de hacer preguntas sensatas sobre lo que el cliente ha informado ... En la mayoría de los casos, no mencionan algo que no consideran relevante, pero que en realidad es clave.
Telepatía también sería útil ...
Dependiendo del problema, puede obtener volcados WinDbg, por lo general dan una idea bastante buena de lo que está sucediendo. Hemos diagnosticado bastantes problemas que no se estrellaron en los minivolcados.
Para las aplicaciones .Net también utilizamos Trace.Writeline para que el usuario pueda iniciar DbgView y enviarnos la salida.
El procedimiento habitual para esto es esperar que algo así ocurra y agregar una tonelada de información de registro. Por supuesto, no lo habilita desde el principio, sino solo cuando esto sucede.
Por lo general, a los clientes no les gusta tener que instalar una nueva versión o algunas herramientas de diagnóstico. No es su trabajo hacer su depuración. Y visitar a un cliente para casos como estos rara vez es una opción. Debe involucrar al cliente lo menos posible. Cambiar un interruptor y enviarle un archivo de registro está bien; cualquier cosa más que esto es demasiado.
Me gusta la alternativa de pensar el problema en el baño. Comenzaré tratando de descubrir las diferencias entre mi máquina y la configuración del cliente.
El registro extenso generalmente ayuda.
Es un tema muy complicado. Estaba pensando en escribir algún procedimiento para esto. Acabo de hacer algún procedimiento para este error no reproducible. podría ser útil
Cuando se acordó el Bug. Hay varios factores que podrían ocurrir.
Estoy seguro de que todos los errores son reproducibles. Siempre tengo ojo para este tipo de problemas ..
- Obtenga la información del sistema
- qué otro proceso el cliente hizo antes de eso.
- Periodo de tiempo que ocurre. es raro o frecuente
- su siguiente acción sucedió después del problema (siempre es igual o diferente)
- Encuentra los factores para este error (como desarrollador)
- Encuentre la posición exacta donde ocurrió este problema.
- Encuentre TODO EL SISTEMA Factores en ese momento
- comprobar todas las fugas de memoria o problema de error del usuario o condición incorrecta en el código
- Enumere todos los facotrs que pueden causar este problema.
- Cómo se ven afectados cada uno de estos factores y cuántos son los datos que mantienen esos factores
- Comprobar los problemas de memeory ocurridos
- compruebe que el cliente tenga el código de actualización actual como el suyo
- revisa todo el registro desde al menos 1 mes y encuentra que ha ocurrido alguna operación anormal. mantente al tanto
Estoy a punto de implementar un sistema automático de informe de errores que me devuelve información (actualmente por correo electrónico, aunque podría usar un servicio web) de cualquier excepción que encuentre la aplicación.
De esa forma obtengo (casi) toda la información que haría si estuviera sentado frente al VS2008 y realmente me ayuda a descubrir cuál es el problema.
¡Los clientes también están (por lo general) impresionados de que conozca su problema tan pronto como lo encuentren!
Además, si usa el manejador de errores Application.ThreadException, también puede enviar información sobre excepciones inesperadas.
Hemos tenido un gran éxito al utilizar EurekaLog y publicarlo directamente en FogBugz . Esto nos proporciona un informe de errores que contiene una pila de llamadas, junto con la información relacionada del sistema (otros procesos en ejecución, memoria, detalles de la red, etc.) y una captura de pantalla. Ocasionalmente, los clientes ingresan más información también, lo cual es útil. Ciertamente, en la mayoría de los casos, hace que sea mucho más fácil y rápido corregir errores.
La manera más fácil es siempre ver al cliente en acción (suponiendo que el cliente pueda reproducirlo fácilmente). A menudo, surgen problemas debido a problemas con el entorno de la computadora del cliente, conflictos con otros programas, etc. Estos son detalles que no podrá ver en su plataforma de desarrollo. Entonces una visita al sitio podría ser útil; pero si eso no es conveniente, herramientas como RealVNC podrían ayudar a que el cliente "haga lo suyo".
(observar al cliente en acción también le permite atraparlos en cualquier momento de la WTF que pueda tener)
Ahora, si el problema es intermitente, entonces las cosas se vuelven algo más complicadas. La mejor forma de evitar este problema sería registrar información útil en lugares donde adivine que podrían ocurrir problemas y, tal vez, usar una herramienta como Splunk para indexar los archivos de registro durante el análisis. Una compilación de diagnóstico (es decir, con registro extra) podría ser útil en este caso.
No importa cuán difícil sea un problema no reproducible, aún podemos tener un enfoque estructurado y estratégico para resolverlos, y puedo decir a través de la experiencia que se requiere un pensamiento fuera de cuadro en el 50% de los casos. En términos generales, uno puede clasificar los problemas en diferentes tipos, lo que ayuda a identificar qué herramienta usar. Por ejemplo, si tiene un problema de bloqueo de aplicación no reproducible o un problema de memoria, puede usar los generadores de perfiles y determinar el problema causado por la funcionalidad en particular.
Además, uno de los enfoques más importantes es el registro enriquecido de inforamation. También uso muchas enumeraciones para describir el estado del proceso según el escenario en cuestión. por ejemplo, usé como Iniciado, Activado, En ejecución, Esperando reparación, etc. para describir los estados de programa y los guardé en DB en diferentes etapas.
No tengo este problema muy a menudo, pero si lo hiciera, usaría una aplicación para compartir pantalla o grabada para ver al usuario en acción sin tener que ir allí (a menos que, como dijo, sea cálido y soleado y la compañía pague el viaje).
Puede usar herramientas como Microsoft SharedView o TeamViewer para conectarse a una PC remota e inspeccionar el problema directamente en el sitio. Por supuesto, necesitará cooperación con el cliente.
Recientemente he estado investigando un problema así. En el transcurso de mi compañía, aprendí que, aunque los sistemas informáticos pueden ser complejos, son predecibles, así que tenga fe en que puede encontrar el problema. Mi enfoque para este tipo de problemas es doble:
1) Reúna la información más detallada posible del cliente sobre su falla y analícela meticulosamente para los patrones. Recopila múltiples conjuntos de datos para múltiples ocurrencias de fallas para construir una imagen más clara.
2) Intenta reproducir el error en casa. Continúe haciendo que su sistema sea cada vez más similar al sistema del cliente hasta que pueda reproducirlo, el sistema sea idéntico o no sea práctico hacerlo más similar.
Al hacer esto, considere:
1) Qué diferencias existen entre este sistema y otros sistemas de trabajo.
2) Lo que ha cambiado recientemente en su producto o la configuración de los clientes que ha causado que el problema comience a ocurrir.
Saludos
Una técnica que he encontrado útil es crear una aplicación con un modo de "diagnóstico" integrado (habilitado por un interruptor de línea de comando cuando ejecutas la aplicación). Eso sin duda evita la necesidad de crear versiones personalizadas con el registro adicional.
De lo contrario, parece que lo que estás haciendo es un enfoque tan bueno como cualquier otro.
Uno de los atributos de los buenos depuradores, creo, es que siempre tienen muchas armas en su kit de herramientas. Parece que nunca se "atascan" demasiado tiempo y siempre hay algo más que probar. Algunas de las cosas que se sabe que hago:
- solicitar los volcados de memoria
- instalar un depurador remoto en una máquina cliente
- agregar el código de rastreo a las compilaciones
- agregar código de registro para depuración
- agregar contadores de rendimiento
- agregar parámetros de configuración a varios bits de código sospechoso para que pueda activar y desactivar funciones
- reescribir y refactorizar código sospechoso
- intenta replicar el problema localmente en un SO o máquina diferente
- utilizar herramientas de depuración como el verificador de aplicaciones
- utilizar herramientas de generación de carga de terceros
- escribir herramientas de simulación internamente para la generación de carga cuando lo anterior falló
- utilice herramientas como Glowcode para analizar fugas de memoria y problemas de rendimiento
- reinstalar la máquina cliente desde cero
- obtener volcados de registro y aplicarlos localmente
- usar las herramientas de registro y archivo
Eventualmente, me parece que el error simplemente se rinde por algún tipo de asombro en mi persistencia. O el cliente se da cuenta de que probablemente se trata de una instalación de máquina o cliente o problema de configuración.
Usamos todos los métodos que mencionas progresivamente comenzando con el más fácil y avanzando hacia el más difícil.
Sin embargo, olvidas que a veces el hardware tiene la culpa. Por ejemplo, la memoria podría estar funcionando mal y algún código de cálculo intensivo se comportará de forma extraña lanzando excepciones con diagnósticos extraños. De fuente, funciona en su máquina, ya que no tiene hardware defectuoso.
Se necesita experiencia para identificar dichos errores e insistir en que el cliente intente instalar el programa en otra máquina o verifique el hardware. Una cosa que ayuda mucho es un buen manejo de errores: cuando el código arroja una excepción, debe proporcionar detalles, no solo indicar que algo está mal. Con una buena indicación de error, es más fácil identificar tales problemas sospechosos relacionados con hardware defectuoso.
Yo también tuve estos problemas. Mi solución fue agregar muchos registros y darle al cliente una compilación de depuración con toda la información de depuración posible. Luego, asegúrese de que dr Watson (estaba en Windows NT) haya creado un volcado de memoria con suficiente información. Después de cargar el volcado de memoria en el depurador, pude averiguar dónde y por qué se colgó.
EDITAR: Oh, esto obviamente solo funciona si la aplicación termina violentamente ...
Copilot (suponiendo que el cliente está en algún lugar frío y lluvioso :)
Solo una pequeña anécdota (de ahí ''wiki de la comunidad''): La semana pasada pensé que era una idea inteligente en una aplicación Django importar el módulo pprint
para imprimir datos de Python solo si DEBUG era Verdadero:
if settings.DEBUG:
from pprint import pprint
Luego usé aquí y allá el comando pprint
como declaración de depuración:
pprint(somevar) # show somevar on the console
Después de terminar el trabajo, probé la aplicación con la configuración DEBUG=False
. Puede adivinar lo que sucedió: el sitio se rompió con errores de HTTP500 en todas partes, y no sabía por qué, porque no hay rastreo si DEBUG
es False
. Me sorprendió que los errores desaparecieran mágicamente, si volvía al modo de depuración.
Me llevó 1-2 horas poner declaraciones de print
todo el código para encontrar que el código se bloquea exactamente en la línea anterior de pprint()
. Luego me tomó otra media hora convencerme a mí mismo de dejar de golpear mi cabeza sobre la mesa.
Ahora viene la moraleja de la historia:
No todo lo que parece una idea inteligente a primera vista es tan inteligente al final.
Un punto importante a tener en cuenta para la depuración de estos errores son todas las opciones de configuración y los conmutadores de plataforma que su código hace por sí mismo. Esto puede ser mucho más que solo algunas preferencias del usuario. Documente bien, si realiza una suposición sobre la plataforma del usuario (por ejemplo, si prueba solo para Win / Mac / Linux, ¿su código se bloqueará en BSD o Solaris?)
Aclamaciones,