En nuestro proyecto contamos con dos bases de datos. Una MySQL para la gestión de usuarios y permisos y otra noSQL donde almacenamos los logs y otras muchas cosas. Pero queremos visualizar los datos de MongoDB en Grafana.

La ventaja de la que disponemos así, es que la gran mayoría de peticiones que se lanzan contra nuestra base de datos, son a la noSQL, lo que agiliza la respuesta de estas peticiones.

No obstante, hemos encontrado un pequeño problema al disponer de todos los datos “valiosos” para el estudio y validación de nuestro modelo de negocio en la base no relacional. Mostrar los datos en Grafana, para poder crear cuadros de mando no es permitido de manera nativa desde MongoDB, así que hemos optado por crear una opción alternativa.

La idea ha sido crear un pequeño programa que nos solventa este problema. Hemos desarrollado un script que se encarga de exportar los datos de nuestra base de datos en MongoDB (noSQL) y los importa luego en una base de datos MySQL (relacional) para que sea fácil acceder a ella desde Grafana. Esto no es ningun gasto de recurso excesivo para nuestro servidor, ya que estos datos son solo accesibles para Grafana y no hacemos uso de ellos en nuestra aplicación.

Un pequeño inconveniente con esto, es que los datos que podamos utilizar en Grafana, serán los que tengamos importados con fecha de la última vez que se haya ejecutado el script. Así tendremos los datos de MongoDB en Grafana de la última vez que se ejecutó el script, cosa que hemos mejorado, haciendo que el script se ejecute diariamente con una tarea Cron de linux, de manera automática. Con esto, hemos solucionado el problema casi por completo, si es cierto que no tenemos los datos en tiempo real, pero lo máximo que podemos estimar es que serán datos de hace 24h si los visualizamos justo antes de que se ejecute el script; también hay que mencionar que si quisiéramos, podríamos ejecutar el script manualmente.

A continuación vamos a describir el funcionamiento de todo lo anterior con un tutorial:

Primero creamos la base de datos que va a ser accesible para Grafana, es decir, la relacional, en nuestro caso es MySQL (MariaDB).

Accedemos a MariaDB como usuario root:

mysql -u root -p

o si no:

sudo mysql -u root -p

Una vez dentro vamos a crear la base de datos y las tablas que necesitamos con sus campos, una opción es exportar el tipo de tabla que necesitamos desde MySQL, y copiar en la terminal la respuesta. Por ejemplo, nosotros tenemos una base de datos noSQL y queremos pasarla a MySQL, así que vamos a crear una base de datos con nombre “sinteticos” con una tabla que se llama “prueba” y que los campos serán: _id, uso_horario, autor, destinatario, msj y fecha. La base de datos que vamos a crear en MySQL es así, porque nuestra colección que vamos a querer ver de MongoDB en Grafana se llama prueba y tiene esos campos. Esto nos quedaría algo así:

CREATE DATABASE IF NOT EXISTS sinteticos /*!40100 DEFAULT CHARACTER SET utf8 */;
USE sinteticos;

-- Volcando estructura para tabla sinteticos.prueba
CREATE TABLE IF NOT EXISTS prueba (
  _id int(11) DEFAULT NULL,
  uso_horario varchar(50) DEFAULT NULL,
  autor int(11) DEFAULT NULL,
  destinatario int(11) DEFAULT NULL,
  msj varchar(50) DEFAULT NULL,
  fecha date DEFAULT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

Si todo ha funcionado bien ahora deberíamos ver que dentro de MariaDB, estamos usando la tabla “sinteticos”:

$MariaDB [sinteticos]>

Esto indica que estamos dentro de la tabla y podemos ejecutar comandos dentro, vamos a ver que está todo creado correctamente:

describe prueba;

Esto nos devuelve todas las columnas de nuestra tabla prueba, y vemos si está todo en orden. En nuestro caso todo está correcto.

+--------------+-------------+------+-----+---------+-------+
| Field        | Type        | Null | Key | Default | Extra |
+--------------+-------------+------+-----+---------+-------+
| _id          | int(11)     | YES  |     | NULL    |       |
| uso_horario  | varchar(50) | YES  |     | NULL    |       |
| autor        | int(11)     | YES  |     | NULL    |       |
| destinatario | int(11)     | YES  |     | NULL    |       |
| msj          | varchar(50) | YES  |     | NULL    |       |
| fecha        | date        | YES  |     | NULL    |       |
+--------------+-------------+------+-----+---------+-------+
6 rows in set (0.002 sec)

Ahora desde el mismo terminal, salimos de MariaDB y vamos a crear el script. Con el comando “exit;” saldremos de nuevo a la terminal. Vamos a crear un fichero que se llamará “migrarBD” para que sea descriptivo. Mediante el comando “cd” vamos a navegar a donde queráis poner el fichero y lo creamos. Lo vamos a crear con la extensión “.sh” ya que va a ser un ejecutable.

touch migrarDB.sh

o si no:

sudo touch migrarDB.sh

Y a continuación entramos con el editor que más os guste, vim, nano…

nano migrarDB.sh

o si no:

sudo nano migrarDB.sh

Una vez dentro del archivo vamos a decirle en primer lugar que es un fichero “bash” y por lo tanto va a poder ejecutarse, esto se hace añadiendo en la primera línea:

#!/bin/bash

Y ahora vamos a escribir los comandos. Primero haremos la exportación de la base de datos de MongoDB, a un fichero csv. 

sudo mongoexport --host localhost --db sinteticos --collection prueba --type=csv --out text.csv --fields _id,uso_horario,autor,destinatario,msj,fecha

Para mayor comodidad os describo que es cada campo:

  • –host: indica donde está alojada vuestra base de datos, en nuestro caso “localhost” porque está en la misma máquina donde ejecutamos el script.
  • –db: nombre de la base de datos que vamos a exportar
  • –collection: nombre de la colección que vamos a exportar.
  • –type: es el tipo de fichero en el cual se guarda la información exportada, nosotros la guardamos en csv porque es la que mejor resultados nos ha dado, pero también se puede guardar en json por ejemplo.
  • –out: nombre del fichero, evidentemente con su extensión correspondiente “text.csv” en nuestro caso.
  • –fields: campos que van a ser exportados, como no hay opción de indicarle todos, hay que escribirlos uno a uno, separados por comas y sin espacios.

Este comando va a generar el “text.csv” con la información de exportado en el directorio donde tenemos el script, pero se le puede cambiar la ruta añadiéndola en el nombre del fichero, del estilo “–out fichero/text.csv” si quisiéramos guardarlo en una carpeta dentro del directorio actual. Pero previamente deberíamos de crear esa carpeta a mano “mkdir fichero”.

Una vez tenemos el archivo exportado, queremos que el script lo importe a nuestra base de datos relacional.

sudo mysqlimport --local -u root --ignore-lines=1 --fields-terminated-by=, sinteticos ./text.csv

Aquí debéis de tener en cuenta lo siguiente:

  • –local: porque vamos a hacer una importación de un fichero local.
  • -u : indica el usuario con el que lo haremos, en nuestro caso “root”
  • –ignore-lines=1, esto indica que vamos a ignorar la linea 1 del fichero, que en csv es el nombre de las columnas.
  • –fiels-terminated-by=, : esto indica que los campos acaban con “,” que es como se hace en csv.
  • sinteticos: es el nombre de nuestra base de datos MySQL donde vamos a importar el fichero
  • text.csv : es basicamente “./ficheroexportado.csv”, que es el fichero que hemos exportado previamente. Si habéis cambiado la ruta, tendréis que indicarla “fichero/text.csv”

Le hemos añadido un poco de texto para que sea más visual si lo ejecutamos a mano, y quedaría algo así:

#!/bin/bash
echo "exportamos la base de datos de mongodb..."
sudo mongoexport --host localhost --db sinteticos --collection prueba --type=csv --out text.csv --fields _id,uso_horario,autor,destinatario,msj,fecha
echo "importamos la base de datos exportada de mongodb a mysql..."
sudo mysqlimport --local -u root --ignore-lines=1 --fields-terminated-by=, sinteticos ./text.csv

Una vez que tenemos esto ya está casi todo. ¿Qué pasa? Que para poder tener en Grafana los datos actualizados de esta tabla, habría que ejecutar este script cada vez que quisiéramos actualizar, lo que supondría tener que entrar al servidor, así que vamos a ejecutarlo de manera automática cada 24h. ¿Cómo? 

Pues aprovechando que nuestro servidor es linux, vamos a crear una tarea Cron que lo ejecute; esto no es más que una tarea programada.

Teniendo claro en que directorio está nuestro script “migrarDB.sh” ejecutamos lo siguiente:

crontab -e

o si no:

sudo crontab -e

Esto va a abrir un fichero con texto comentado, que nos explica cómo crear la tarea programada, pero vamos a saltarnos todo eso y vamos a ir directamente a la última línea y vamos a escribir un comando del siguiente estilo:

m h dom mon dow command

donde:

  • m : minutos
  • h : hora
  • dom: día del mes
  • mon: mes
  • dow: dia de la semana
  • command: qué comando o acción se va a ejecutar, podríamos poner aquí por ejemplo, borrar un fichero, reiniciar el sistema o lo que fuese necesario.

En nuestro caso vamos a ejecutar el script cada día a las 03:30 (de madrugada, para no interferir en las posibles acciones de los usuarios en el sistema) de la siguiente manera:

30 03 * * * /home/usuario/migrarDB.sh

Los asteriscos (*) indican que se ejecutará siempre, es decir, todos los días del mes, todos los meses y todos los días de la semana.

Ahora guardamos y salimos “Ctrl+X” y “Intro” en mi caso, porque se está editando con “nano” y ya tenemos nuestro script preparado para ejecutarse cada día a las 18:30 y migrar nuestros datos de MongoDB (noSQL) a MySQL para poder acceder a ellos desde Grafana.

Cabe destacar que esta no es la forma más optima, ya que estamos exportando e importando continuamente todos los datos; por lo que llegado un nivel alto de usuarios y registro de acciones, estamos moviendo muchos datos. Lo ideal para seguir visualizando los datos de MongoDB en Grafana de este modo, sería con un exportado e importado incremental; solo con los datos que hay nuevos o modificados, pero por ahora, esto nos vale.

Con esto, solo nos quedaría configurar nuestro Grafana. Cear un Data a la base de datos de MySQL que hemos creado con los datos de MongoDB y crear un Dashboard con estos datos. Si queréis saber más podéis consultar la documentación oficial de Grafana, o podéis pedírnoslo y estaremos encantados de hacerlo.

Esperamos que te haya sido de ayuda, y si tienes alguna pregunta o sugerencia, no dudes en contactar con nosotros a través de comentarios, o de nuestro formulario de contacto.

en_GBEnglish
es_ESSpanish en_GBEnglish