Además de PostgreSQL y MySQL, en nuestra organización utilizamos servidores de gestión de bases de datos IBM Informix. Se trata de un producto de software de gestión de bases de datos propietario, licenciado por IBM, que corre sobre sistemas Unix.
Al tratarse de software propietario, collectd (y creo que ninguna otra solución de recolección de métricas) no posee un plugin para monitorear servidores de bases de datos Informix. Por ende me dispuse a crear un script Bash que permita monitorear servidores Informix y almacene las métricas en una base de datos InfluxDB, el cual comparto en este artículo.
Según la página en Wikipedia, Informix es una familia de productos RDBMS de IBM, adquirida en 2001 a una compañía (también llamada Informix o Informix Software) cuyos orígenes se remontan a 1980. El DBMS Informix fue concebido y diseñado por Roger Sippl a finales de los años 1970. Durante parte de los años 1990 fue el segundo sistema de bases de datos más popular después de Oracle. En 2001 IBM, impulsada por una sugerencia de Wal-Mart (el mayor cliente de Informix) compró Informix. IBM tenía planes a largo plazo tanto para Informix como para DB2, compartiendo ambas bases de datos tecnología de la otra. La última versión actual de Informix es la 12.10.xC12 (liberada el 20 de julio de 2018)
Informix incluye la herramienta de monitoreo onstat
, la cual permite verificar el estado del servidor en todo momento. Esta herramienta tiene una gran cantidad de opciones y provee mucha información estadística sobre el motor de bases de datos.
La idea detrás de este script es interpretar la salida del comando onstat -p
(profile) y enviar los valores a una base de datos InfluxDB (utilizando la API HTTP).
Veamos cómo es la salida típica de onstat -p
:
[informix@ifxdb ~]$ onstat -p IBM Informix Dynamic Server Version 11.70.FC7GE -- On-Line -- Up 3 days 23:06:21 -- 217312 Kbytes Profile dskreads pagreads bufreads %cached dskwrits pagwrits bufwrits %cached 132546 171039 24139564 99.45 83144 233945 1230187 93.42 isamtot open start read write rewrite delete commit rollbk 22771017 56515 374149 19350401 479845 305533 25200 19201 0 gp_read gp_write gp_rewrt gp_del gp_alloc gp_free gp_curs 0 0 0 0 0 0 0 ovlock ovuserthread ovbuff usercpu syscpu numckpts flushes 0 0 0 192.56 88.05 112 112 bufwaits lokwaits lockreqs deadlks dltouts ckpwaits compress seqscans 398 4 1749780 0 0 0 79048 36490 ixda-RA idx-RA da-RA logrec-RA RA-pgsused lchwaits 0 10821 104358 0 99704 5659
El objetivo es transformar los valores en esta salida a consultas InfluxQL.
Para comenzar, remover líneas en blanco y recuperar sólo las líneas a partir de "Profile":
[informix@ifxdb ~]$ onstat -p | grep -v "^$" | awk '/Profile/{y=1;next}y' dskreads pagreads bufreads %cached dskwrits pagwrits bufwrits %cached 132546 171039 24139564 99.45 83144 233945 1230187 93.42 isamtot open start read write rewrite delete commit rollbk 22771017 56515 374149 19350401 479845 305533 25200 19201 0 gp_read gp_write gp_rewrt gp_del gp_alloc gp_free gp_curs 0 0 0 0 0 0 0 ovlock ovuserthread ovbuff usercpu syscpu numckpts flushes 0 0 0 192.58 88.06 112 112 bufwaits lokwaits lockreqs deadlks dltouts ckpwaits compress seqscans 398 4 1749780 0 0 0 79048 36490 ixda-RA idx-RA da-RA logrec-RA RA-pgsused lchwaits 0 10821 104358 0 99704 5659
Luego eliminar los espacios en blanco extra al final de cada línea, y reemplazar el resto de los espacios en blanco por una única coma:
[informix@ifxdb ~]$ onstat -p | grep -v "^$" | awk '/Profile/{y=1;next}y' | sed 's/[[:space:]]*$//' | sed 's/ \{1,\}/,/g' dskreads,pagreads,bufreads,%cached,dskwrits,pagwrits,bufwrits,%cached 132546,171039,24139564,99.45,83144,233945,1230187,93.42 isamtot,open,start,read,write,rewrite,delete,commit,rollbk 22771017,56515,374149,19350401,479845,305533,25200,19201,0 gp_read,gp_write,gp_rewrt,gp_del,gp_alloc,gp_free,gp_curs 0,0,0,0,0,0,0 ovlock,ovuserthread,ovbuff,usercpu,syscpu,numckpts,flushes 0,0,0,192.60,88.07,112,112 bufwaits,lokwaits,lockreqs,deadlks,dltouts,ckpwaits,compress,seqscans 398,4,1749780,0,0,0,79048,36490 ixda-RA,idx-RA,da-RA,logrec-RA,RA-pgsused,lchwaits 0,10821,104358,0,99704,5659
Finalmente es necesario utilizar un par de bucles para agrupar cada clave con su correspondiente valor. En cada iteración del bucle exterior, recuperar dos líneas de la salida anterior. Cada línea se convierte a un arreglo (separado por comas). Luego se concatena cada clave (ítem del primer arreglo) con su correspondiente valor (ítem del arreglo 2).
El resultado es el siguiente:
[informix@ifxdb ~]$ while read -r L1 && read -r L2; do > IFS=',' read -r -a A1 <<< "$L1" > IFS=',' read -r -a A2 <<< "$L2" > > for (( I=0; I<${#A1[@]}; I++ )); > do > echo "informix_value,host=ifxdb,type=profile,type_instance=${A1[I]} value=${A2[I]}" > done > > done <<< "$ONSTAT_PROFILE" informix_value,host=ifxdb,type=profile,type_instance=dskreads value=132546 informix_value,host=ifxdb,type=profile,type_instance=pagreads value=171039 informix_value,host=ifxdb,type=profile,type_instance=bufreads value=24139604 informix_value,host=ifxdb,type=profile,type_instance=%cached value=99.45 informix_value,host=ifxdb,type=profile,type_instance=dskwrits value=83144 informix_value,host=ifxdb,type=profile,type_instance=pagwrits value=233945 informix_value,host=ifxdb,type=profile,type_instance=bufwrits value=1230187 informix_value,host=ifxdb,type=profile,type_instance=%cached value=93.42 informix_value,host=ifxdb,type=profile,type_instance=isamtot value=22771038 informix_value,host=ifxdb,type=profile,type_instance=open value=56515 informix_value,host=ifxdb,type=profile,type_instance=start value=374150 informix_value,host=ifxdb,type=profile,type_instance=read value=19350418 informix_value,host=ifxdb,type=profile,type_instance=write value=479845 informix_value,host=ifxdb,type=profile,type_instance=rewrite value=305533 informix_value,host=ifxdb,type=profile,type_instance=delete value=25200 informix_value,host=ifxdb,type=profile,type_instance=commit value=19201 informix_value,host=ifxdb,type=profile,type_instance=rollbk value=0 informix_value,host=ifxdb,type=profile,type_instance=gp_read value=0 informix_value,host=ifxdb,type=profile,type_instance=gp_write value=0 informix_value,host=ifxdb,type=profile,type_instance=gp_rewrt value=0 informix_value,host=ifxdb,type=profile,type_instance=gp_del value=0 informix_value,host=ifxdb,type=profile,type_instance=gp_alloc value=0 informix_value,host=ifxdb,type=profile,type_instance=gp_free value=0 informix_value,host=ifxdb,type=profile,type_instance=gp_curs value=0 informix_value,host=ifxdb,type=profile,type_instance=ovlock value=0 informix_value,host=ifxdb,type=profile,type_instance=ovuserthread value=0 informix_value,host=ifxdb,type=profile,type_instance=ovbuff value=0 informix_value,host=ifxdb,type=profile,type_instance=usercpu value=192.66 informix_value,host=ifxdb,type=profile,type_instance=syscpu value=88.11 informix_value,host=ifxdb,type=profile,type_instance=numckpts value=112 informix_value,host=ifxdb,type=profile,type_instance=flushes value=112 informix_value,host=ifxdb,type=profile,type_instance=bufwaits value=398 informix_value,host=ifxdb,type=profile,type_instance=lokwaits value=4 informix_value,host=ifxdb,type=profile,type_instance=lockreqs value=1749780 informix_value,host=ifxdb,type=profile,type_instance=deadlks value=0 informix_value,host=ifxdb,type=profile,type_instance=dltouts value=0 informix_value,host=ifxdb,type=profile,type_instance=ckpwaits value=0 informix_value,host=ifxdb,type=profile,type_instance=compress value=79048 informix_value,host=ifxdb,type=profile,type_instance=seqscans value=36491 informix_value,host=ifxdb,type=profile,type_instance=ixda-RA value=0 informix_value,host=ifxdb,type=profile,type_instance=idx-RA value=10821 informix_value,host=ifxdb,type=profile,type_instance=da-RA value=104358 informix_value,host=ifxdb,type=profile,type_instance=logrec-RA value=0 informix_value,host=ifxdb,type=profile,type_instance=RA-pgsused value=99704 informix_value,host=ifxdb,type=profile,type_instance=lchwaits value=5659
Perfecto, en este punto se ha logrado convertir la salida de onstat -p
en un batch de consultas InfluxQL. El nombre de métrica elegido es "informix_value" (en concordancia con los nombres de métrica utilizados por collectd). Cada valor se relaciona a su clave a través del tag "type_instance".
Finalmente resta insertar este batch de métricas en la base de datos InfluxDB utilizando la API HTTP. Las consultas se envían a través del método HTTP POST a la siguiente URL: http://192.168.140.65:8086/write?db=collectd
.
El script resultante es el siguiente:
#!/bin/bash INFLUXDB_USER="informix" INFLUXDB_PASS="1234" INFLUXDB_URL="http://192.168.140.65:8086/write?db=collectd" HOST=$(hostname) MEASUREMENT="informix_value" TAG="$MEASUREMENT,host=$HOST,type=profile" ONSTAT_PROFILE=$(onstat -p | grep -v "^$" | awk '/Profile/{y=1;next}y' | sed 's/[[:space:]]*$//' | sed 's/ \{1,\}/,/g') while read -r L1 && read -r L2; do IFS=',' read -r -a A1 <<< "$L1" IFS=',' read -r -a A2 <<< "$L2" for (( I=0; I<${#A1[@]}; I++ )); do echo "$TAG,type_instance=${A1[I]} value=${A2[I]}" done done <<< "$ONSTAT_PROFILE" | curl -u $INFLUXDB_USER:$INFLUXDB_PASS -i -XPOST "$INFLUXDB_URL" --data-binary @- >/dev/null 2>&1 || exit 1
Configurar adecuadamente las variables INFLUXDB_USER
, INFLUXDB_PASS
, INFLUXDB_URL
, HOST
y MEASUREMENT
. Luego guardar el script en una ubicación conveniente (/usr/local/bin/
).
Dejo este script en mi cuenta de GitHub: linuxitux / scripts / misc / informix-profile-influxdb.bash.
Finalmente es necesario ejecutar periódicamente este script utilizando un cronjob:
[informix@ifxdb ~]$ crontab -e
Por ejemplo, para ejecutar una vez por minuto:
# Monitoreo con InfluxDB+Grafana * * * * * /usr/local/bin/informix-profile-influxdb.bash
Habilitar la API HTTP en InfluxDB
A fin de poder escribir estos datos en la base InfluxDB, es necesario que la API HTTP esté habilitada.
En el servidor donde se ha instalado InfluxDB, permitir el acceso remoto a la API HTTP editando el archivo de configuración:
# nano /etc/influxdb/influxdb.conf
Por defecto sólo se permite el acceso desde localhost:
[http] enabled = true bind-address = "127.0.0.1:8086"
Es posible asignar una IP en la red local, o permitir que escuche en todas las interfaces configuradas ingresando 0.0.0.0
:
[http] enabled = true bind-address = "0.0.0.0:8086"
En este caso se recomienda luego filtrar el acceso mediante un firewall.
Reiniciar InfluxDB:
# service influxdb restart
A continuación, y si se ha habilitado el uso de autenticación (cosa altamente recomendable), es necesario crear un usuario con privilegios de escritura en la base de datos destino ("collectd", en este caso).
Iniciar el cliente influx
y conectarse al motor con privilegios de administración:
# influx -username admin -password '' password: Visit https://enterprise.influxdata.com to register for updates, InfluxDB server management, and monitoring. Connected to http://localhost:8086 version 1.0.2 InfluxDB shell version: 1.0.2 >
Crear el usuario (según la configuración en el script) y otorgarle permisos de escritura sobre la base de datos destino:
> create user informix with password '1234' > grant all on "collectd" to "informix" > quit
Si todo es correcto, será posible comenzar a visualizar las métricas de Informix recolectadas por el script.
Tener en cuenta que la mayoría de las métricas son contadores, con lo cual resulta útil convertirlas a deltas aplicando la transformación derivada a fin de lograr una gráfica conveniente en Grafana:

La página Web Oninit: Onstat Reference - onstat -p Profile statistics provee una descripción detallada de cada uno de los valores en las diferentes salidas del comando onstat
, lo cual permite identificar fácilmente qué valores resulta útil monitorear.
Referencias
- onstat - Server Status Line
- onstat -p Profile statistics
- The onstat utility - IBM Knowledge Center
- Writing data with the HTTP API
- Authentication and authorization in InfluxDB
Tal vez pueda interesarte