Beneficios del registro estructurado frente al registro básico

110

Estamos creando una nueva aplicación y me gustaría incluir el registro estructurado. Mi configuración ideal sería algo así como Serilognuestro código C # y Bunyannuestro JS. Estos alimentarían fluentdy luego podrían salir a cualquier cantidad de cosas, estaba pensando inicialmente elasticsearch + kibana. Ya tenemos una base de datos MySQL, por lo que a corto plazo estoy más interesado en obtener la configuración de Serilog + Bunyan y los desarrolladores para usarla, y podemos iniciar sesión en MySQL mientras tomamos un poco más de tiempo para incorporar fluidez y el resto.

Sin embargo, uno de nuestros codificadores más experimentados preferiría hacer algo como: log.debug("Disk quota {0} exceeded by user {1}", quota, user);usar log4nety luego ejecutar sentencias select contra MySQL como:SELECT text FROM logs WHERE text LIKE "Disk quota";

Dicho esto, ¿qué enfoque es mejor y / o qué cosas debemos tener en cuenta al elegir el tipo de sistema de registro?

DTI-Matt
fuente
Estoy de acuerdo con las ediciones que se hicieron. No estoy tratando tanto de demostrarle algo a alguien sino de comprender los beneficios y la diferencia en la tala estructurada frente a la tala básica. En mi opinión, estructurado nos da mucha más flexibilidad, especialmente en las fuentes de registros, y cómo podemos mostrar sus datos. A mi entender, no puedo explicar por qué el registro básico y la búsqueda en MySQL es mejor / peor que el registro estructurado.
DTI-Matt
2
El registro estructurado de @ DTI-Matt serilog es solo un registro básico, solo formatea los objetos que imprime en él, algo que puede hacer usted mismo al anular ToString con mucha facilidad. Un aspecto más importante es la configuración y gestión de los archivos de registro, no una forma de formatear una cadena sobre otra, otra es el rendimiento. Si el desarrollador quiere usar log4net (que es una buena biblioteca de registro), entonces su elección de serilog (que se ve bien) es una de esas "soluciones en busca de un problema".
gbjbaanb
@ DTI-Matt Al mirar el serilog se ve muy similar a log4net. log4net maneja la creación de registros estructurados en la configuración. No necesita buscar los mensajes de registro ya que puede tener información adicional configurada y escrita en una tabla. También configure log4net para fluentd tipstuff.org/2014/05/…
RubberChickenLeader el
Cuidado, hay algunos tontos que no entienden la idea de las preguntas conceptuales aquí. preguntar sobre la dirección de las aplicaciones de la base de datos en un intento de controlar sus capacidades de ETL v. código le dará algunos votos negativos serios. Supongo que tu pregunta también estará en el corte.
user3916597
2
@gbjbaanb Serilog funciona de la misma manera que log4net cuando procesa eventos como texto, pero si usa un formato estructurado para almacenar registros, asociará propiedades con nombre a los argumentos que se pasan (es decir, para permitir la búsqueda / filtrado sin expresiones regulares, etc. ) HTH!
Nicholas Blumhardt

Respuestas:

140

Hay dos avances fundamentales con el enfoque estructurado que no se pueden emular usando registros de texto sin (a veces niveles extremos) de esfuerzo adicional.

Tipos de eventos

Cuando escribe dos eventos con log4net como:

log.Debug("Disk quota {0} exceeded by user {1}", 100, "DTI-Matt");
log.Debug("Disk quota {0} exceeded by user {1}", 150, "nblumhardt");

Estos producirán un texto similar:

Disk quota 100 exceeded by user DTI-Matt
Disk quota 150 exceeded by user nblumhardt

Pero, en lo que respecta al procesamiento automático, son solo dos líneas de texto diferente.

Es posible que desee encontrar todos los eventos de "cuota de disco excedida", pero el caso simplista de buscar eventos like 'Disk quota%'se reducirá tan pronto como ocurra otro evento con el siguiente aspecto:

Disk quota 100 set for user DTI-Matt

El registro de texto desecha la información que inicialmente tenemos sobre el origen del evento, y esto debe reconstruirse al leer los registros, generalmente con expresiones de coincidencia cada vez más elaboradas.

Por el contrario, cuando escribe los siguientes dos eventos Serilog :

log.Debug("Disk quota {Quota} exceeded by user {Username}", 100, "DTI-Matt");
log.Debug("Disk quota {Quota} exceeded by user {Username}", 150, "nblumhardt");

Estos producen una salida de texto similar a la versión de log4net, pero detrás de escena, ambos eventos llevan la "Disk quota {Quota} exceeded by user {Username}" plantilla de mensaje .

Con un receptor apropiado, más tarde puede escribir consultas where MessageTemplate = 'Disk quota {Quota} exceeded by user {Username}'y obtener exactamente los eventos donde se superó la cuota de disco.

No siempre es conveniente almacenar la plantilla de mensaje completa con cada evento de registro, por lo que algunos hunden la plantilla de mensaje en un EventTypevalor numérico (por ejemplo 0x1234abcd), o puede agregar un enriquecedor a la canalización de registro para hacerlo usted mismo .

Es más sutil que la siguiente diferencia a continuación, pero es enormemente poderosa cuando se trata de grandes volúmenes de registro.

Datos estructurados

Una vez más, considerando los dos eventos sobre el uso del espacio en disco, puede ser bastante fácil usar registros de texto para consultar a un usuario en particular like 'Disk quota' and like 'DTI-Matt'.

Pero, el diagnóstico de producción no siempre es tan sencillo. ¿Imagina que es necesario encontrar eventos donde la cuota de disco excedida fuera inferior a 125 MB?

Con Serilog, esto es posible en la mayoría de los sumideros utilizando una variante de:

Quota < 125

La construcción de este tipo de consulta a partir de una expresión regular es posible, pero se cansa rápido y por lo general termina siendo una medida de último recurso.

Ahora agregue a esto un tipo de evento:

Quota < 125 and EventType = 0x1234abcd

Aquí comienza a ver cómo estas capacidades se combinan de manera directa para hacer que la depuración de producción con registros se sienta como una actividad de desarrollo de primera clase.

Un beneficio adicional, quizás no tan fácil de prevenir por adelantado, pero una vez que la depuración de producción se ha eliminado de la tierra de la piratería de expresiones regulares, los desarrolladores comienzan a valorar mucho más los registros y a tener más cuidado y consideración al escribirlos. Mejores registros -> aplicaciones de mejor calidad -> más felicidad por todas partes.

Nicholas Blumhardt
fuente
44
Me encanta esta respuesta. Muy bien escrito y por alguna razón que no puedo explicar, me mantiene al borde de mi asiento.
jokab
16

Cuando recopila registros para procesar, ya sea para analizar en alguna base de datos y / o buscar en los registros procesados ​​más adelante, el uso del registro estructurado hace que parte del procesamiento sea más fácil / más eficiente. El analizador puede aprovechar la estructura conocida ( por ejemplo , JSON, XML, ASN.1, lo que sea) y usar máquinas de estado para el análisis, a diferencia de las expresiones regulares (que pueden ser computacionalmente caras (relativamente) compilar y ejecutar). El análisis de texto de forma libre, como el sugerido por su compañero de trabajo, tiende a depender de expresiones regulares y a que el texto no cambie . Esto puede hacer que el análisis de texto de forma libre sea bastante frágil ( es decir, el análisis está estrechamente acoplado al texto exacto en el código).

Considere también el caso de búsqueda / búsqueda, por ejemplo :

SELECT text FROM logs WHERE text LIKE "Disk quota";

LIKElas condiciones requieren comparaciones con cada textvalor de fila; De nuevo, esto es relativamente costoso desde el punto de vista computacional, particularmente cuando se usan comodines:

SELECT text FROM logs WHERE text LIKE "Disk %";

Con el registro estructurado, su mensaje de registro relacionado con errores de disco podría verse así en JSON:

{ "level": "DEBUG", "user": "username", "error_type": "disk", "text": "Disk quota ... exceeded by user ..." }

Los campos de este tipo de estructura pueden mapearse con bastante facilidad, por ejemplo , a los nombres de columna de la tabla SQL, lo que significa que la búsqueda puede ser más específica / granular:

SELECT user, text FROM logs WHERE error_type = "disk";

Puede colocar índices en las columnas cuyos valores espera buscar / buscar con frecuencia, siempre que no utilice LIKEcláusulas para esos valores de columna . Cuanto más pueda dividir su mensaje de registro en categorías específicas, más específico podrá hacer su búsqueda. Por ejemplo, además del error_typecampo / columna en el ejemplo anterior, podría hacer incluso be "error_category": "disk", "error_type": "quota"o somesuch.

La mayor estructura que tiene en sus mensajes de registro, los sistemas más su análisis sintáctico / búsqueda (como fluentd, elasticsearch, kibana) puede tomar ventaja de esta estructura, y llevar a cabo sus tareas con mayor rapidez y menos CPU / memoria.

¡Espero que esto ayude!

Castaglia
fuente
1
+1 Quiero agregar que no se trata solo de velocidad y eficiencia. La relevancia de los resultados de búsqueda será mucho mayor cuando se utilice el registro estructurado y, por lo tanto, las "consultas estructuradas". Sin esa búsqueda de cualquier palabra que ocurra en diferentes contextos, obtendrá toneladas de resultados irrelevantes.
Marjan Venema
1
+1 de mí también, creo que esto lo clava. Se agregó una formulación ligeramente diferente a continuación, para ampliar también el caso de los tipos de eventos.
Nicholas Blumhardt
8

No encontrará muchos beneficios del registro estructurado cuando su aplicación cree unos cientos de mensajes de registro por día. Definitivamente lo hará cuando tenga unos cientos de mensajes de registro por segundo provenientes de muchas aplicaciones diferentes implementadas.

Relacionado, la configuración donde los mensajes de registro terminan en ELK Stack también es apropiada para la escala en la que el registro en SQL se convierte en un cuello de botella.

He visto la configuración de "inicio de sesión y búsqueda básicos" con SQL select .. likey expresiones regulares llevadas a sus límites donde se desmorona: hay falsos positivos, omisiones, código de filtro horrible con errores conocidos que es difícil de mantener y nadie quiere tocar, nuevos mensajes de registro que no siguen los supuestos del filtro, renuencia a tocar las declaraciones de registro en el código para que no rompan los informes, etc.

Por lo tanto, están surgiendo varios paquetes de software para abordar este problema de una mejor manera. Está Serilog, escuché que el equipo de NLog lo está mirando y escribimos StructuredLogging.Jsonpara Nlog , también veo que las nuevas abstracciones de registro de ASP.Net "hacen posible que los proveedores de registro implementen ... registro estructurado".

Un ejemplo con StructuredLogging. Inicia sesión en un registrador NLog como este:

logger.ExtendedError("Order send failed", new { OrderId = 1234, RestaurantId = 4567 } );

Estos datos estructurados van a kibana. El valor 1234se almacena en el OrderIdcampo de la entrada del registro. Luego puede buscar usando la sintaxis de consulta kibana para, por ejemplo, todas las entradas de registro donde @LogType:nlog AND Level:Error AND OrderId:1234.

Messagey OrderIdahora son solo campos en los que se pueden buscar coincidencias exactas o inexactas según lo necesite, o agregados para conteos. Esto es poderoso y flexible.

De las mejores prácticas de StructuredLogging :

El mensaje registrado debe ser el mismo cada vez. Debe ser una cadena constante, no una cadena formateada para contener valores de datos como identificadores o cantidades. Entonces es fácil de buscar.

El mensaje registrado debe ser distinto, es decir, no el mismo que el mensaje producido por una declaración de registro no relacionada. Luego, buscarlo no coincide con cosas no relacionadas también.

Antonio
fuente