Monitorización II - Generando gráficos de datos Ad Hoc


Table Of Contents

Este artículo es el segundo de una serie de artículos sobre monitorización que estamos publicando en PostgreSQL-es. En el vamos a ver como podemos generar gráficos de una manera fácil a partir de los datos generados usando monitorización Ad Hoc.

En el artículo anterior de la serie, “Monitorización”, hablamos de dos tipos de monitorización, Ad Hoc y Preventiva.

En el tipo de monitorización Ad Hoc utilizabamos diferentes programas para obtener información de nuestros sistemas. Ahora vamos a ver como podemos procesar estos datos de una manera fácil, rápida y efectiva para crear gráficos que podamos utilizar en informes o simplemente que nos ayuden a entender lo que ha ocurrido durante un periodo de monitorización Ad Hoc.

En este artículo solamente vamos a generar con gnuplot unos gráficos sobre el uso de algunos recursos del sistema, pero no olvidar que el mismo método explicado aquí se puede también utilizar para generar gráficos de los datos internos o procesados en PostgreSQL.

Para nuestros ejemplos hemos generado cierta carga en nuestro sistema con el programa bonnie++ y hemos utilizado dos programas, iostat y vmstat para recoger información de nuestro sistema durante el periodo de pruebas. Todo lo presentado en este artículo está realizado en un sistema Linux y ejecutado desde la linea de comandos en una terminal.

Si no teneis instalado gnuplot, bonnie++, iostat y/o vmstat podeis instalarlos (en un sistema debian/ubuntu) con:

  $ sudo apt-get install procps
  $ sudo apt-get install sysstat
  $ sudo apt-get install bonnie++
  $ sudo apt-get install gnuplot

Recolectando datos

Primero creamos un directorio en nuestro sistema para grabar todos los datos que vamos a generar en nuestras pruebas:

  $ cd 
  $ mkdir monitorizacion_pruebas

A continuación ejecutamos iostat y vmstat cada segundo durante aproximadamente 14 minutos (850 seg), y redireccionamos el resultado a dos ficheros con los que despues trabajaremos. La ejecución completa por defecto de bonnie++ en mi portatil tarda unos 12 o 13 minutos, asi que si recogemos datos durante 14 minutos tendremos datos de toda la ejecución. Si no sabemos el tiempo exacto que deberiamos recoger datos, podriamos omitir el valor 850 y parar manualmente los dos procesos iostat y vmstat cuando decidamos que tenemos suficientes datos recogidos.

  $ cd ~/monitorizacion_pruebas/
  $ `iostat -k -p 1 850 > iostat.log &` && `vmstat 1 850 > vmstat.log &`

Una vez que hemos empezado a recoger datos con iostat y vmstat, arrancamos el programa bonnie++ para generar una buena carga en el sistema de almacenamiento. Este programa genera I/O con lecturas/escrituras sequenciales y peticiones al azar de datos.

  $ cd ~/monitorizacion_pruebas/
  $ time bonnie++ -d /tmp/ > bonnie.output

Cuando la ejecución de bonnie++, iostat y vmstat termine tendremos tres ficheros en nuestro directorio de pruebas ~/monitorizacion_pruebas/

  $ cd ~/monitorizacion_pruebas/
  $ ls -l
  total 576
  -rw-r--r-- 1 rafael rafael   1027 2011-03-16 20:11 bonnie.output
  -rw-r--r-- 1 rafael rafael 459063 2011-03-16 20:13 iostat.log
  -rw-r--r-- 1 rafael rafael  73812 2011-03-16 20:13 vmstat.log

Con el programa bon_csv2html podriamos generar un fichero html con el resultado de la ejecución de bonnie++, para su posterior consulta en un navegador si estais interesados en estos datos.

  $ cd ~/monitorizacion_pruebas/
  $ bon_csv2html bonnie.output > bonnie.html 2> /dev/null

Un pequeño ejemplo del contenido del fichero iostat.log seria:

Linux 2.6.35-25-generic (E6410)    02/28/2011 	_x86_64	   (4 CPU)

avg-cpu:  %user   %nice %system %iowait  %steal   %idle
           2.98    0.06    1.38    1.82    0.00   93.76

Device:            tps    kB_read/s    kB_wrtn/s    kB_read    kB_wrtn
sda              24.18       379.80        87.36     998814     229744
sda1             11.52       260.27        31.28     684457      82260
sda2             11.75       116.29        46.46     305820     122192
sda3              0.02         0.12         0.00        328          0
sda4              0.75         3.05         9.62       8025      25292

Y un pequeño ejemplo del contenido del fichero iostat.log:

 procs -----------memory---------- ---swap-- -----io---- -system-- ----cpu----
 r  b   swpd   free   buff  cache   si   so    bi    bo   in   cs us sy id wa
 0  0      0 5703648 216500 1156552    0    0    93    21   90  407  3  1 94  2
 0  0      0 5703568 216500 1156816    0    0     0     0  225  658  0  1 99  0
 0  0      0 5703648 216500 1156804    0    0     0    24  231  639  0  0 99  0
 0  0      0 5703296 216508 1156800    0    0     0    28  211  585  0  0 98  1
 1  0      0 5703472 216508 1156644    0    0     0     0  246  727  0  1 99  0

Procesando datos

Una vez que hemos llegado a este punto tenemos que empezar a procesar los ficheros iostat.log y vmstat.log para extraer los datos que nos interesan y de los cuales queremos crear gráficos. Esto se podria hacer de muchas maneras, incluso editando manualmente estos ficheros con vuestro editor favorito.

Como estamos trabajando en sistemas Linux/Unix y en terminal, podemos hacer uso de un gran número de herramientas disponibles por defecto en nuestros sistemas. Estas herramientas nos van a facilitar enormemente el procesamiento de nuestros datos y nos evitarán un tedioso trabajo manual. También vamos a utilizar “tuberias” (|) para mandar el resultado de un comando a otro comando y a redireccionar(>) los resultados a ficheros.

Para generar los gráficos que queremos con gnuplot tendremos que generar series de datos que se puedan representar en un sistema de coordenadas cartesianas en el plano o espaciales.

Principalmente tendremos que realizar dos operaciones con nuestros datos, seleccionar las filas que nos interesen y dentro de estas filas elegir las columnas que necesitemos.

Para elegir las filas que nos interesan utilizaremos el comando grep o egrep (grep -E). Y para elegir las columnas utilizaremos el comando awk.

Primero vamos a extraer los datos del número de Kb/s que hemos leido (kB_read/s)y escrito (kB_wrtn/s) en la partición /dev/sda1 (donde bonnie++ ha generado I/O en nuestro sistema). Estos datos están representados en la columna 3 y 4 del fichero iostat.log.

Para extraer todas las filas que nos interesan, elegimos con egrep todas las filas que contienen sda1.

Y para elegir las columnas usamos awk y extraemos las columnas en las posiciones 3 y 4 empezando a contar desde la izquierda. A mi me gusta trabajar más en MBytes, como los datos de estas columnas están en Kbytes, voy a dividir los valores por 1024 para transformarlos a Mbytes.

Como mencionamos en el primer artículo de la serie, la primera fila del resultado por defecto de iostat y vmstat da los valores medios desde la última vez que se arranco el sistema. Esta fila no la queremos, una manera de evitar esta fila es utilizar tail para escoger todas las filas a partir de la segunda.

Ahora solo queda poner todo esto junto con tuberias y redireccionar el resultado a un fichero llamado iostat_read_write.log

  $ cd ~/monitorizacion_pruebas/
  $ egrep sda1 iostat.log | awk -F ' ' '{print $3/1024,$4/1024}' | tail -n+2 > iostat_read_write.log

El fichero iostat_read_write.log tendrá en nuestro caso 849 filas con dos columnas en cada fila. Los valores en vuestro sistema no serán, por supuesto, los mismos que en este artículo.

  $ cd ~/monitorizacion_pruebas/
  $ cat iostat_read_write.log

  0.0351562 0
  0 0.03125
  0 0
  0 0
  0 0
  ...........
  ...........
  0 0

Segundo vamos a extraer los datos referentes al uso de CPU. Estos datos están representados en las últimas cuatro columnas (us sy id wa)del fichero vmstat.log

Para extraer todas las filas que no son cabeceras, elegimos con egrep todas las filas que no contienen la palabra procs o swpd.

Y para elegir las ultimas cuatro columnas usamos awk y extraemos las columnas en las posiciones 13,14,15 y 16 empezando a contar desde la izquierda.

Al igual que con iostat, utilizamos tail para desechar la primera fila de nuestro resultado.

Ahora solo queda poner todo esto junto con tuberias y redireccionar el resultado a un fichero llamado vmstat_cpu.log

  $ cd ~/monitorizacion_pruebas/
  $ egrep -v "(procs|swpd)" vmstat.log | awk -F ' ' '{print $13,$14,$15,$16}' | tail -n+2 > vmstat_cpu.log

El fichero vmstat_cpu.log tendra en nuestro caso 849 filas con cuatro columnas en cada fila.

  $ cd ~/monitorizacion_pruebas/
  $ cat vmstat_cpu.log 

  3 2 95 0
  4 2 92 2
  4 2 95 0
  2 3 95 0
  4 3 93 1
  ........
  ........
  1 2 97 0

Generando gráficos

Una vez que hemos recolectado los datos y los hemos procesado para elegir lo que queremos representar gráficamente, podemos usar el programa gnuplot para generar estos gráficos.

Las posibilidades de representación que nos brinda gnuplot son enormes y en un principio la cantidad de comandos y parámetros disponibles son abrumadores y nos puede parecer una tarea y un programa muy difícil de usar. En este artículo no tenemos tiempo de profundizar en el uso de gnuplot, pero veremos que no necesitamos tanto para empezar a utilizarlo y generar nuestros primeros gráficos.

gnuplot se puede utilizar de manera interactiva o via scripts. Para empezar a usarlo de manera interactiva podeis escribir gnuplot en vuestra terminal y empezar a escribir comandos.

Aquí teneis un ejemplo, escribir el comando plot sin(x) una vez arrancado el programa, ¿Qué pasa cuando haceis esto?:

  $ gnuplot

  G N U P L O T
  Version 4.4 patchlevel 0
  last modified March 2010
  System: Linux 2.6.35-27-generic
  
  Copyright (C) 1986-1993, 1998, 2004, 2007-2010
  Thomas Williams, Colin Kelley and many others
  
  gnuplot home:     http://www.gnuplot.info
  faq, bugs, etc:   type "help seeking-assistance"
  immediate help:   type "help"
  plot window:      hit 'h'

  Terminal type set to 'wxt'
  
  gnuplot> plot sin(x)
  
  gnuplot> quit

El comando help os puede ayudar mucho cuando empeceis a profundizar en el uso de este programa.

Como hemos dicho, nosotros vamos a usar el programa via scripts. Lo primero que vamos a hacer es crear un pequeño y simple script para generar un fichero PNG con la gráfica correspondiente a los MB/s de lectura en sda1.

Creamos un fichero llamado iostat_mb_s_read.gnuplot con este contenido:

  # Definimos que los resultados sean 
  # un fichero PNG en vez de en pantalla 
  set term png font "freesans"
  set autoscale
  
  # Definimos el nombre de nuestro grafico
  set output "iostat_mb_s_read.png"
  
  # Definimos el titulo del grafico
  set title "Uso /dev/sda1"
  
  # Definimos que las leyendas del grafico
  # esten fuera del sistema de coordenadas
  set key outside
  
  # Definimos que se utilicen todas las muestras
  set xrange[0:849]
  
  # Definimos que se muestre un borde y 
  # se cuadricule el sistema de coordenadas
  set border
  set grid
  
  # Definimos una leyenda para el eje de
  # las X y las Y del grafico de lecturas
  set ylabel "MBytes/s lectura"
  set xlabel "Muestras"
  
  # Generamos el grafico utilizando la 
  # columna 1 del fichero iostat_read_write.log
  plot "iostat_read_write.log" using 1 title "Mb/s read" smooth bezier with lines linewidth 2

Y ejecutamos este comando para generar el gráfico PNG que hemos definido:

  $ cd ~/monitorizacion_pruebas/
  $ gnuplot iostat_mb_s_read.gnuplot

Este comando generara un gráfico PNG llamado iostat_mb_s_read.png con este contenido:

Podemos seguir complicando la cosa. Ahora vamos a generar un solo gráfico con dos curvas, una para las lecturas y otra para las escrituras. Primero creamos otro script llamado iostat_mb_s_read_write.gnuplot con este contenido:

  # Definimos que los resultados sean 
  # un fichero PNG en vez de en pantalla 
  set term png font "freesans"
  set autoscale

  # Definimos el nombre de nuestro grafico
  set output "iostat_mb_s_read_write.png"
  
  # Definimos el titulo del grafico
  set title "Uso /dev/sda1"
  
  # Definimos que las leyendas del grafico
  # esten fuera del sistema de coordenadas
  set key outside
  
  # Definimos que se utilicen todas las muestras
  set xrange[0:849]
  
  # Definimos que se muestre un borde y 
  # se cuadricule el sistema de coordenadas
  set border
  set grid
  
  # Definimos una leyenda para el eje de
  # las X y las Y del grafico
  set ylabel "MBytes/s"
  set xlabel "Muestras"
  
  # Generamos el grafico utilizando la 
  # columna 1 del fichero iostat_read_write.log
  # para lecturas y la columna 2 para escrituras 
  plot "iostat_read_write.log" using 1 title "Mb/s read" smooth bezier with lines linewidth 2,"iostat_read_write.log" using 2 title "Mb/s write" smooth bezier with lines linewidth 2

Y ejecutamos este comando para generar el gráfico PNG que hemos definido:

  $ cd ~/monitorizacion_pruebas/
  $ gnuplot iostat_mb_s_read_write.gnuplot

Esto comando generara un grafico PNG llamado iostat_mb_s_read_write.png con este contenido:

Como podeis ver tenemos las dos curvas representadas en el mismo gráfico.

Para terminar vamos a dar un último ejemplo en donde generamos un gráfico con varios subgráficos dentro del mismo. Vamos a representar los valores de CPU que tenemos en el fichero vmstat_cpu.log.

Para esto creamos otro script llamado vmstat_cpu_multi.gnuplot con este contenido:

  # Definimos que los resultados sean 
  # un fichero PNG en vez de en pantalla 
  set term png font "freesans"
  set autoscale
  
  # Definimos el nombre de nuestro grafico
  set output "vmstat_cpu_multi.png"
  
  # Definimos que las leyendas del grafico
  # no se muestren
  set key off
  
  # Definimos cada cuantas muestras se 
  # muestran los valores en el eje X
  set xtics 150

  # Definimos que el rango de los valores
  # en el eje de las Y sea de 0 a 100
  set yrange[0:100]
  
  # Definimos que se muestre un borde y 
  # se cuadricule el sistema de coordenadas
  set border
  set grid
  
  # Definimos una leyenda para el eje de
  # las X y las Y del grafico de lecturas
  set ylabel "Porcentaje de uso (%)"
  set xlabel "Muestras"
  
  # Definimos que vamos a crear un grafico con 
  # multiples subgraficos en el mismo.
  set multiplot
  
  # Definimos que el tamaño relativo del primer subgrafico 
  # sea el 50% del espacio disponible en el ancho y alto 
  # del grafico principal
  set size 0.5, 0.5
  
  # Definimos que el punto (0,0) de este subgrafico
  # este en punto relativo (0,0) del grafico principal
  set origin 0, 0
  
  # Definimos el titulo de este subgrafico
  set title "CPU-user"
  
  # Generamos el subgrafico utilizando la 
  # columna 1 del fichero vmstat_cpu.log
  plot "vmstat_cpu.log" using 1 title "cpu-user" smooth bezier with filledcurves x1 linecolor rgbcolor "#ffa500"
  
  # Definimos que el tamaño relativo del segundo subgrafico 
  # sea el 50% del espacio disponible en el ancho y alto 
  # del grafico principal
  set size 0.5, 0.5
  
  # Definimos este subgrafico a la derecha del primero
  set origin 0.5, 0
  
  # Definimos el titulo de este subgrafico
  set title "CPU-system"
  
  # Generamos el subgrafico utilizando la 
  # columna 2 del fichero vmstat_cpu.log
  plot "vmstat_cpu.log" using 2 title "cpu-system" smooth bezier with filledcurves x1 linecolor rgbcolor "#228b22"
  
  # Definimos que el tamaño relativo del tercer subgrafico 
  # sea el 50% del espacio disponible en el ancho y alto 
  # del grafico principal
  set size 0.5, 0.5
  
  # Definimos este subgrafico arriba del primero
  set origin 0, 0.5
  
  # Definimos el titulo de este subgrafico
  set title "CPU-idle"
  
  # Generamos el subgrafico utilizando la 
  # columna 3 del fichero vmstat_cpu.log
  plot "vmstat_cpu.log" using 3 title "cpu-idle" smooth bezier with filledcurves x1 linecolor rgbcolor "#483d8b"
  
  # Definimos que el tamaño relativo del cuarto subgrafico 
  # sea el 50% del espacio disponible en el ancho y alto 
  # del grafico principal
  set size 0.5, 0.5
  
  # Definimos este subgrafico arriba y a la derecha 
  # del primero
  set origin 0.5, 0.5
  
  # Definimos el titulo de este subgrafico
  set title "CPU-waiting"
  
  # Generamos el subgrafico utilizando la 
  # columna 4 del fichero vmstat_cpu.log
  plot "vmstat_cpu.log" using 4 title "cpu-waiting" smooth bezier with filledcurves x1 linecolor rgbcolor "#ffd700" 
  unset multiplot

Y ejecutamos este comando para generar el gráfico PNG que hemos definido:

  $ cd ~/monitorizacion_pruebas/
  $ gnuplot vmstat_cpu_multi.gnuplot

Esto comando generará un gráfico PNG llamado vmstat_cpu_multi.png con este contenido:

Como podeis ver las posibilidades son infinitas y todo depende de lo que necesitais representar en el gráfico y el tipo de gráfico que quereis generar. Lo normal es crearse unos scripts en BASH u otro lenguaje de alto nivel que podais utilizar para generar los diferentes tipos de gráficos, sin necesidad de tener que estar modificando/creando todo el tiempo scripts con los comandos de gnuplot.

Y hasta aquí el contenido de este artículo. Si en vez de generar ficheros PNG con los gráficos quereis mostrar la información en pantalla, podeis borrar los commandos set term png …. y set output …. de todos vuestros ficheros *.gnuplot

Ya solo os queda leer más documentación sobre gnuplot y practicar.

Enlaces: