¿Cómo me acerco a corregir un error irreproducible / que ocurre al azar?

11

Tenemos un sitio web multilingüe en el que se descubrió un error hace unos días. Estaba mostrando datos de otros idiomas en otro idioma y también se seleccionó la combinación de datos como el idioma inglés, pero también mostraba datos de otros idiomas en la página y viceversa. Lo hace con poca frecuencia pero está presente en el sitio web. Revisar el código tampoco ayuda porque esto no siempre ocurre.

¿Alguna sugerencia para encontrar el problema de manera oportuna? Estoy pidiendo estrategias aquí.

maz3tt
fuente
44
comience a probar el código para situaciones que permitirán que ocurra este error (en lugar de hacerlo al revés)
Imran Omar Bukhsh

Respuestas:

20

El primer paso es tratar de caracterizar lo que puede causar este tipo de problema. Como esto está relacionado con la selección del idioma correcto para las secciones del código, comience por considerar lo siguiente:

  • ¿Cómo se detecta el idioma? ¿Se basa en información de la solicitud HTTP? ¿Se basa en la información de la sesión ?, ¿o se basa en los campos de la base de datos? En esencia, ¿puede ser un problema relacionado con la forma en que su aplicación selecciona el idioma para cada sección?
  • ¿Cómo se muestra el idioma? ¿Está sacando de un archivo de propiedades o una base de datos? ¿Es posible que la referencia al idioma correcto se pierda de alguna manera? ¿El lenguaje mixto que ves siempre es el predeterminado para el sitio?
  • ¿Existe una correlación con el entorno del cliente? Esto está relacionado con la primera viñeta, pero va un poco más allá. He tenido problemas de representación extraños debido a los servidores proxy de almacenamiento en caché aguas abajo. Por lo general, esos tipos de problemas son una página entera que está obsoleta o que sirve la página de una persona a otros usuarios (eso fue vergonzoso).
  • ¿Está utilizando un valor de hilo local? Si se maneja una solicitud en mi más de un subproceso, el valor local del subproceso tendrá información diferente según el subproceso que esté funcionando en ese momento. En un entorno de servidor web, no puede suponer que el subproceso en el que comenzó a procesar será el mismo subproceso en el que completa el procesamiento, a menos que sea parte de la especificación de su plataforma. Los escritores de servidores han descubierto que si reutilizan un pequeño grupo de subprocesos y trabajan en multiplex en trozos, pueden manejar más solicitudes simultáneamente. Incluso si tiene un subproceso desde el principio hasta el final de una solicitud, el servidor puede estar multiplexando otras solicitudes en ese subproceso al mismo tiempo. En lugar de locales de subprocesos, considere vincular ese valor a los atributos de solicitud o sesión.

Ahora, una vez que ha caracterizado a las posibilidades de lo que puede salir mal, es el momento para asegurarse de que tiene los datos que necesita para tratar de averiguar lo que hizo mal camino.

  • Use el registro profuso alrededor de las áreas problemáticas. Este es un lugar donde una herramienta como Log4J o Log4Net realmente puede brillar. Ese marco de registro, y otros similares, le permite subir el registro de ciertas categorías mientras mantiene el ruido para todo lo demás, todo cambiando un archivo de configuración. Desea introducir nuevas declaraciones de registro para determinar si lo que sospecha podría ser el problema. También asegúrese de que sus registros de acceso HTTP tengan toda la información que desea sobre cada solicitud (cookies, parámetros de encabezado http, etc.)
  • Intenta simular el problema. Dado que esto sucede esporádicamente, ¿cómo es la carga en el servidor en el momento en que ocurre? ¿Te golpean varias solicitudes simultáneas de una combinación de idiomas? Si es así, intente simular ese tipo de carga en su entorno de prueba. Una herramienta similar a JMeter podría ser lo que necesita. También querrás poder falsificar direcciones IP para tus clientes falsos. Recuerde que las direcciones IP están divididas para que pueda determinar en qué país / región se basa la IP en los dos primeros segmentos de la dirección.
  • El problema será igual de esporádico en su entorno de prueba, pero a medida que se reduce a su causa real, puede sesgar los resultados para que suceda con más frecuencia que en la naturaleza. Además, puede revisar más fácilmente los archivos de registro e intentar aprender de ellos.
  • Es un proceso iterativo, así que sea paciente. Debe inducir el tipo de carga que cree que reproducirá el error, verificará los registros y refinará sus pruebas en función de lo que encuentre. Lo importante es identificar el problema , así que resista el impulso de hacer algunas soluciones simples que podrían hacer que el problema real ocurra con menos frecuencia.

Finalmente, una vez que haya reducido el problema hasta el punto en que sepa cómo reproducirlo y qué lo causa, escriba la prueba automatizada más pequeña que pueda para forzar el problema en el código. Si ha reducido el problema a una clase, o un par de clases que no funcionan juntas correctamente, reprodúzcalo en ese nivel. No debería tener que generar 100 hilos para hacerlo, solo haga la prueba más pequeña que puede causar que el problema ocurra el 100% del tiempo.

Ahora puede solucionarlo y tener la confianza razonable de que no volverá a morderlo nuevamente.

Berin Loritsch
fuente
10

El error no es irreproducible. Simplemente no has descubierto cómo reproducirlo todavía.

Ningún error es aleatorio a menos que esté lanzando una excepción basada en el valor de retorno de alguna instrucción Random ().

Sé que esto puede parecer una semántica, pero es tranquilizador mentalmente decirte esto a ti mismo.

Es muy difícil y frustrante descubrir cómo reprobar un error que solo ocurre debido a condiciones de carrera complejas o similares.

En cuanto a cómo encontrarlo, activaría / agregaría algunos registros a la aplicación en lugares que podrían brindarle más información.

Luego diga a las personas que están viendo el error (ya sean Devs, QA, usuarios finales) que informen tan pronto como lo vean con el momento en que sucedió y luego consulten sus registros. Pídales otra información, ya que el error solo puede ocurrir debido a la interacción de varios sistemas diferentes o debido a una condición de carrera

Esperemos que puedas encontrar una pista.

Gilles
fuente
incluso las llamadas Random () no son realmente aleatorias a menos que se deriven de un generador de ruido blanco de hardware. Son psuedo-random, lo que significa que los números se distribuyen matemáticamente en el orden más aleatorio posible. Pero si comienza desde el mismo valor "semilla", obtendrá la misma respuesta cada vez.
Berin Loritsch
1
@Berin: lo sé.
Gilles
+1 para "todavía no has descubierto cómo reproducirlo". Todos los errores tienen una causa raíz o de lo contrario no sucederían.
Mike S
1
No tiene que estar fuera de Aleatorio (), las cosas que dependen del tiempo, especialmente aquellas que involucran acceso incorrecto a un recurso compartido pueden ser muy difíciles de reproducir.
Loren Pechtel
2
@Gilles: Excepto que pueden no ser deterministas en nada que pueda medir razonablemente. (Digamos, exactamente cuando se lanzó alguna otra tarea, es tiempo).
Loren Pechtel,
5

Puede intentar encontrar lugares en su código donde pueda reconocer que ocurrió el problema (parámetros inconsistentes en un método, por ejemplo), agregar las verificaciones a su código y dejar que agreguen información adicional al registro de depuración (como un seguimiento de pila, objetos agregado a la sesión, etc.)

Al hacerlo, con un poco de suerte, puede capturar información sobre los sucesos y deducir su camino de regreso al problema.

rsp
fuente
2

La automatización debería ayudar, si son los mismos pasos para reproducir que a veces fallan, automatizar eso y ponerlo en un bucle. Corre 50,000 veces y es muy probable que ocurra.

Kieren Johnstone
fuente
El evento no es aleatorio, solo parece aleatorio. Hacer esto puede hacer que aparezca, pero le dará muy poca información sobre por qué apareció.
Josh K
1
@Josh: si no puede reproducirlo, esta puede ser una buena manera de hacerlo y obtener un seguimiento de la pila con símbolos de depuración, por ejemplo. Me imagino que es un gran primer paso, verlo de primera mano
Kieren Johnstone
Estás asumiendo que hay una pila y que se puede obtener. No nos ha brindado ninguna información técnica sobre la aplicación o cuán accesible es para la depuración bajo este tipo de carga. Esta no es una estrategia de depuración , está golpeándola con un martillo tratando de atrapar el momento exacto en que se rompe.
Josh K
@ Josh: mi experiencia en el mundo real me dice que lo más valioso en la investigación / reparación de un error es verlo de primera mano. Ya sea algo con el tiempo que puede ver, un seguimiento de la pila, algo en los registros o cualquier otra cosa. Siempre que sea posible, tener problemas aparentemente aleatorios probados en un bucle me ha llevado allí muy rápidamente. Si tiene una idea diferente, publíquela como una respuesta por el amor de Dios: este es un método válido y una respuesta válida.
Kieren Johnstone
No estoy de acuerdo, y creo que la respuesta de Berin es la forma correcta de resolver esto.
Josh K
1

intente encontrar patrones para precisar las condiciones que hacen que este problema se manifieste. Eso debería apuntar hacia las secciones de su código que fallan (o se comportan de manera inconsistente).

jwenting
fuente
No shit ..............
theringostarrs
0

¿Puedes detectar cuándo está ocurriendo el problema ? Si es así, ¿puede volcar de manera confiable la información sobre el estado del sistema en ese punto?

Si la respuesta a ambas preguntas es sí, instrumente su código para registrar tanta información como sea posible cuando realmente ocurra el error, luego espere.

Esto no es un reemplazo de lo que otros han sugerido (todavía tendrá que razonar sobre cómo el código puede entrar en el estado que está viendo), pero mientras no pueda reproducir el error a voluntad, Es una buena idea no perder las ocasiones en que aparece.

jimwise
fuente