Gráficas basadas en tiempo: Graphite


En esta ocasión voy a escribir sobre Graphite, una utilidad para generar gráficas basadas en tiempo.

Una vez tengamos Graphite instalado, se podrá utilizar para distintos usos: contar las visitas a una web, contar las ejecuciones de un programa, medir el tiempo de ejecución de un programa, ...

Veremos que es un programa sencillo de manejar, pero muy potente.

Entendiendo Graphite

Antes de meternos en harina, es importante tener claros los conceptos.

Graphite es una herramienta Django que permite graficar lo almacenado en una base de datos Round Robin llamada whisper. También permite guardar eventos discretos (luego lo vemos).

Por tanto, podremos mostrar información, pero Graphite no guarda esa información. Eso se delega en otros servicios, como Carbon:

b'\nn "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">\n\n\n\n\ngraphite_basic_flow\n\n\nProgram 1\n\nProgram 1\n\n\nCarbon\n\nCarbon\n\n\nProgram 1->Carbon\n\n\n\n\nWhisper\n\nWhisper\n\n\nCarbon->Whisper\n\n\nescribir\n\n\nProgram 2\n\nProgram 2\n\n\nProgram 2->Carbon\n\n\n\n\nGraphite\n\nGraphite\n\n\nGraphite->Whisper\n\n\nleer\n\n\nBrowser\n\nBrowser\n\n\nBrowser->Graphite\n\n\n\n\n\n'

Whisper es una base de datos de tipo Round Robin. Eso significa que tiene una especie de "casillas" (slots) que se rellenan cada cierto tiempo. Cuando se han rellenado todas, se comienza otra vez por el principio. De esta manera, el tamaño de la base de datos es siempre fijo, permitiéndonos calcularlo antes de comenzar a medir.

El problema de las bases de datos de este tipo es cuando se reciben varios valores en un slot de tiempo. En estos casos se opta por la media o bien por el último de los valores. El tamaño de estos slots se realiza en el archivo /etc/carbon/storage-schemas.conf. Ejemplo:

[carbon]
pattern = ^carbon\.
retentions = 60:90d

[local]
pattern = ^local\.
retentions = 1:1h

[default_1min_for_1day]
pattern = .*
retentions = 60s:1d

Como se puede observar, el formato es sencillo.

Existen más piezas en este puzzle, que iremos introduciendo a lo largo de otros posts. Este artículo se centrará en los que se ven.

Instalando Graphite

Como no sólo tenemos que instalar Graphite sino también Carbon, lo más sencillo es usar:

apt-get install graphite-web graphite-carbon

A continuación tendremos que configurar el Django detrás de Graphite. Esta información se encuentra en /usr/share/doc/graphite-web/README.Debian, pero voy a repetirla aquí.

Si sólo queremos probar Graphite, lo más sencillo es hacer, como root:

su -s /bin/bash -c '/usr/bin/django-admin runserver --settings graphite.settings 0.0.0.0:8080' _graphite

Eso utiliza el servidor web de Django y una base de datos sqlite, que puede no ser suficiente para producción, pero es ideal para probarlo rápidamente.

En producción, por el contrario, será mejor montarlo de una forma más decente, usando Apache httpd, por ejemplo:

  1. Instalar wsgi para Apache httpd:

    apt-get install libapache2-mod-wsgi
    
  2. Copiar los valores por defecto que ya nos proporciona el paquete Debian de Graphite:

    cp /usr/share/graphite-web/apache2-graphite.conf /etc/apache2/sites-available/graphite-web.conf
    
  3. Habilitarlo:

    a2ensite graphite-web
    
  4. Reiniciar apache:

    service apache2 restart
    

Si también queremos usar MySQL o PostgreSQL en lugar de sqlite, tendremos que modificar la configuración de Graphite, que se encuentra en /etc/graphite/local_setting.py y que es equivalente a la de cualquier Django.

Si habéis trabajado con Django, sabréis que el programa principal se suele llamar manage.py... Pues el de Graphite es accesible invocando graphite-manage en su lugar.

Primeros pasos en Graphite

Asumiendo que se ha optado por la vía rápida, ejecutando el runserver, o bien una configuración similiar, tendremos Graphite escuchando en el puerto 8080, y podremos acceder a él: http://localhost:8080

Probablemente se queje porque la clave SECRET_KEY utilizada es el valor por defecto. Podéis ignorarlo o arreglarlo editando su valor en el archivo /etc/graphite/local_setting.py y poniendo un valor aleatorio y grande.

Pues ya está, ya tenemos Graphite corriendo. No ha sido tan duro.

Como también instalamos Carbon, éste ya se ha puesto a insertar valores por su cuenta. En la interfaz, veréis un árbol a la izquierda que podéis ir desplegando. Los nodos pintarán gráficas:

Página por defecto de Graphite

Si pensáis que la interfaz es horrible, sólo os diré que la han mejorado desde la última vez que entré.

Abajo tenéis los botones Graph Options y Graph Data permiten modificar la forma de los gráficos u operar sobre los datos. Volveremos sobre esto en la sección de la API.

A la derecha veréis varios botones, donde me centraré en dos: Dashboard y Events.

Graphite Dashboard

En un intento por hacer Graphite algo más usable, hicieron el Dashboard, que no es más que otra aberración para la vista:

Dashboard de Graphite

Al menos tiene completion.

Permite generar paneles y así gestionar varias gráficas de una vez. De todas maneras, es mejor hacer eso con Grafana, como veremos en próximos posts.

Graphite Events

Si hemos pulsado en el botón de Events, veremos una página horrible que dice:

> No events. Add events using the admin interface or by posting (eg, curl -X POST http://localhost:8000/events/ -d '{"what": "Something Interesting", "tags" : "tag1 "}')

Recomiendo hacerle caso, aunque tendréis que cambiar el puerto, sólo por probar:

curl -X POST http://localhost:8080/events/ -d '{"what": "Something Interesting", "tags" : "tag1 "}'

Y, si recargamos la página, veremos el evento. Esto será útil para registrar acciones no periódicas: una actualización de configuración, una ejecución de Puppet, etc. Veremos más sobre su uso en el post sobre Grafana.

Puntos fuertes de Graphite

Algún lector dirá: "bueno, pues si la interfaz es tan horrible como dices, ¿por qué nos cuentas todo esto?".

Interfaz GET

Y tendría toda la razón, pero es que Graphite tiene una interfaz, accesible por GET, muy versátil y molona.

Por ejemplo... obtenemos la URL de la imagen anterior, obtendremos: http://localhost:8080/render/?width=586&height=308&_salt=1436083979.749&target=carbon.agents.nightcrawler-a.avgUpdateTime

Vamos por partes:

http://localhost:8080/render/
Punto de acceso a la API
width=586
Ancho que tendrá la imagen.
height=308
Alto que tendrá la imagen.
_salt=1436083979.749
Podéis ignorarlo. Es la semilla utilizada en caso de usar valores aleatorios.
target=carbon.agents.nightcrawler-a.avgUpdateTime
Lo que se está pintando.

El target permite realizar operaciones, tales como sumar diferentes series, filtrar valores, etc. Por ejemplo, para mostrar el percentil 90 de las consultas a la caché de carbon:

target=percentileOfSeries(carbon.agents.nightcrawler-a.cache.queries,0.9)

También se pueden obtener los valores guardados con el argumento format. Recomiendo echar un ojo a toda la API de Graphite.

Interfaz POST

Carbon también tiene una interfaz POST que permite insertar datos en Whisper y así renderizarlos desde Graphite. Por defecto estará escuchando en el puerto 2003:

echo "local.random.diceroll 4 `date +%s`" | nc -q0 localhost 2003

Como se puede observar, el formato es my sencillo:

  • Nombre de la métrica, separando por puntos los distintos niveles. Esto permite generar una especie de árbol, por lo que se recomienda colocar los términos más genéricos al principio y los más específicos al final.
  • Valor de la métrica.
  • timestamp, en formato UNIX

Ejemplo de uso de Graphite

Aquí os dejo un pequeño ejemplo de uso:

No conté con que $RANDOM se resuelve en el primer shell, por lo que enviaba un valor fijo XD

Conclusión

Graphite es una herramienta mucho más potente de lo que pueda parecer. Lo veremos en próximos posts.

De momento es importante quedarse con la idea principal: generación de gráficos donde el tiempo es el eje X.

En próximos posts veremos cómo graficar información del sistema, cómo embeber estos gráficos en nuestro sistema de alertas o cómo dar soporte a millones de métricas por segundo. Y todo basado en Graphite.


Comentarios

Comments powered by Disqus