sábado, 9 de noviembre de 2019

ELK - Creación de índices y mapeo de campos.

Hoy, tras las entradas anteriores, continuamos trabajando con Elastic para revisar un punto muy importante sobre los campos y el tipo de dato de los mismos. Veremos que en algunos casos será necesario fijar el tipo de dato de un campo, y como podemos reindexar los datos ya disponibles en caso de ser necesario.

En todas las entradas sobre Logstash hasta la fecha hemos enviado los registros de log, generados por syslog_generator, directamente a Logstash donde hemos hecho el mapeo automático de los campos de origen.

Fijándonos en los campos que enviamos mediante syslog_generator, vemos un punto muy interesante sobre los campos de fecha que hemos mapeado al analizar el índice. Podemos consultar el mapeo de campos directamente desde la sección Mapping del índice en cuestión, que podemos encontrar en Index Management:

Mapeo por defecto de campos.
Como podemos ver, los dos campos de hora y fecha que hemos definido procedentes de nuestros hosts son de tipo texto, no de tipo fecha como sería lo correcto. Además, como recordaremos de un post anterior, al crear el patrón sobre el índice que contiene los documentos de Logstash, vimos que usábamos por defecto el campo @timestamp que contiene la fecha y hora de recepción del documento y su introducción en el índice, no la fecha y hora real de generación del evento. Por tanto, ¿que tenemos que hacer para asegurarnos que un campo se mapea con el tipo de dato correcto? y más importante aún ¿puedo cambiar el tipo de dato de un documento ya existente en un índice?

Revisando el resto de campos del índice podemos ver que todos los campos se han mapeado como una cadena, por ejemplo tempsensor_temperature que debería mapearse como un tipo integer. 

Por tanto, salvo que los campos de nuestros documentos sean siempre de tipo texto, está claro que es necesario crear nuestros índices previamente, analizando la información que queremos procesar con Elastic para establecer los mapeos de los campos correctamente y fijando el tipo de dato de los mismos cuando sea necesario.

En un caso como este, en el cual ya tenemos un índice cuyos documentos necesitamos mantener, vamos a tener que realizar una operación de reindexación, en la cual básicamente copiamos el contenido de un índice en otro índice diferente.

Empecemos creando nuestro nuevo índice con los campos mapeados a un valor correcto, para esto lo más sencillo es que usemos directamente la consola interactiva disponible en el menú Dev Tools:

Consola de desarrollo de Elasticsearch.
Comencemos creando un índice nuevo con las mísmas características del índice existente que necesitamos reindexar. Para esto lo más sencillo es que copiemos y peguemos las características del índice ya existente, las cuales podemos obtener utilizando la operación _search con un comando GET NombreDelIndex desde la consola:

Configuración del índice existente.
Copiamos la salida del comando anterior y la pegamos en la consola, cambiando el tipo de dato de los mapeos de los campos que necesitamos así como el nombre del índice. Es importante que definamos el formato de mapeo de los campos de manera correcta o, como veremos, recibiremos un error al realizar la operación de reindexado. Para empezar establecemos el siguiente formato para nuestros campos de fecha y hora:

Especificación de formato para el campo tempsensor_time.

Especificación de formato para el campo tempsensor_timestamp.

El formato de fecha especificado para el campo tempsensor_timestamp es un formato de fecha personalizado, construido a partir de la información dada por la clase DateTimeFormatter de Java, cuya documentación podéis consultar en el siguiente enlace.

Para el campo tempsensor_timestamsp es tan sencillo como definir el campo en el nuevo índice como tipo integer.

Especificación del campo tempsensor_temperature.

Por último cambiamos el tipo de operación a PUT y, si hemos realizado la configuración correctamente, el resultado será más o menos el siguiente:

Resultado de la creación del nuevo índice.
Ahora nuestro nuevo índice aparece en la sección Index Management siendo el número de documentos disponibles cero:

Nuevo índice ya disponible para su uso.
A continuación reindexaremos los documentos existentes en nuestro índice actual, para lo cual usaremos la operación reindex del API de Elasticsearch. Desde la consola de desarrollo lanzamos la operación de reindexado del siguiente modo:

Operación de reindexado.
En caso de utilizar un formato incorrecto, o en nuestro caso al especificar un formato de fecha incorrecto, recibiríamos el siguiente mensaje:

Error de la operación dereindexado debido a un formato incrrecto.
Para utilizar un formato de fecha correcto, os recomiendo consultar la documentación de Elasticsearch en este enlace que nos explica el tipo de dato date, así como este otro enlace que muestra los tipos de formatos de fecha predefinidos que podemos utilizar. Adicionalmente podremos crear un formato de fecha para el tipo date siguiendo la sintaxis dada por la clase DateTimeFormatter de Java.

Tras realizar la operación de reindexado y al crear el index pattern para nuestro nuevo índice, ya vemos la primera diferencia con el índice anterior. Durante la creación del index pattern para Kibana, ya tenemos disponibles nuestros campos de fecha y hora para ser usados como filtros de tiempo para mostrar y analizar los datos:

Selección del filtro de tiempo durante la creación del index pattern.
 
Al terminar la creación del index pattern ya podemos consultar los datos correspondientes a nuestro nuevo índice, obteniendo el siguiente resultado:

Documentos del índice reindexado.
Como podemos ver, Kibana ha completado los nuevos campos con la fecha, en el caso del campo tempsensor_time y con la hora para el campo tempsensor_timestamp.

Empecemos por corregir los campos que contienen la hora y fecha de cada documento. Para evitar este comportamiento solo necesitamos editar cada uno de estos campos desde el menú Index Patterns, dentro de la sección Management, para eliminar la fecha en el caso del campo tempsensor_time y la hora, en el caso del campo tempsensor_timestamp. Podemos verlo en las siguientes imágenes:

Búsqueda de campos en el index pattern de Kibana.
Al pinchar sobre la opción Edit de cada uno de los campos de tipo date, podremos cambiar como se muestran y, por tanto, eliminar la fecha en el caso del campo tempsensor_time:

Corregimos el formato de represenatción del campo tempsensor_time.
Y eliminar la hora en el caso del campo tempsensor_timestamp:

Corregimos el formato de represenatción del campo tempsensor_timestamp.
Con lo que ahora, al volver a la sección Discover ya vemos los campos de fecha y hora correctamente, además de que el campo tempsensor_temperature ya se reconoce de tipo numérico:

Datos del nuevo índice con los campos ya corregidos.
Como hemos visto, Elastic nos proporciona herramientas para manejar los documentos de índices ya existentes. Esto nos permite corregir errores en los mapeos de los campos y cambiarlos de tipo, cuando sea necesario. Evidentemente esto puede ser bastante problemático si tenemos índices con millones de documentos, con lo que es muy importante que estudiemos detenidamente los datos que vamos a enviar antes de crear el índice para evitar tener que realizar este tipo de operaciones.