BOMBOLOM.COM

(mix) Gráficos de sistema

Por Helder Guerreiro.

Existem muitas situações onde a visualização da informação sob a forma de um gráfico facilita a compreensão do que se está a passar. Por exemplo poderá ser normal termos a carga do sistema a 7.0 ou 8.0 durante breves períodos de tempo num servidor de base de dados, podemos estar a fazer a consolidação de dados diária, ou a extrair um dump da base de dados para backup. No entanto já não será normal termos valores de carga do sistema permanentemente neste valores. Se tivermos um gráfico com as variações nas últimas 24H da carga do sistema, facilmente se encontram estes tipos de problemas.

Neste artigo vou apresentar a ferramenta RRDtool que nos permite de uma forma rápida e prática fazer gráficos e não só de dados que variem no tempo.

Introdução

O RRDtool desempenha as seguintes funções:

  1. Cria as bases de dados necessárias para armazenar a informação que queremos mostrar sobre a forma de gráfico;
  2. Faz a gestão destas bases de dados. Como não pudemos armazenar infinita informação, o RRDtool usa várias estratégias para resolver este problema:
    • Por um lado só armazena um número pré-determinado de leituras, por exemplo se armazenarmos uma leitura de 5 em 5 minutos e especificarmos que queremos armazenar apenas 288 leituras, então, ao fim de 24 horas (288*5/60 = 24) começa-se a escrever sobre os primeiros dados que foram inseridos - isto garante que a base de dados nunca ultrapassa um determinado tamanho, evitando assim todo o tipo de manutenção que existe associado a uma base de dados tradicional (controlo de tamanho, ajuste de performance, optimizações, etc);
    • Por outro lado, o RRDtool agrega a informação que recolhe segundo várias estratégias (médias, mínimos, máximos, etc), assim podemos indicar para a mesma variável vários períodos para recolha dos dados. Por exemplo, poderíamos recolher a informação de 5 em 5 minutos e além disso tirar uma média destes valores de hora a hora. Na altura de usar esta informação num gráfico o RRDtool vai tentar escolher a resolução temporal que melhor se ajusta à resolução de um pixel no gráfico.
    • Além dos pontos anteriores o RRDtool apenas armazena leituras em alturas pré-determinadas. Por exemplo que queremos armazenar leituras todos os 10 minutos, ao indicarmos a hora da leitura inicial, pré-determinamos todas as outras leituras. Ao acrescentar a leitura à base de dados o valor é armazenado no ponto mais próximo. Além disso se passar um determinado tempo após o ponto de leitura, então esse ponto poderá ficar sem valor atribuído.
    Quando pedirmos para traçar um gráfico para um determinado período de tempo, o RRDtool vai utilizar os dados que melhor se ajustem.
  3. Finalmente o RRDtool permite-nos traçar os gráficos. Existem um sem número de opções que podem ser utilizadas para ajustar o resultado final. Isto incluí a realização de operações matemáticas sobre os dados recolhidos, vários tipos de representação gráfica, por linhas, áreas, etc.

    Para fazer os gráficos podemos utilizar as ferramentas de linha de comandos incluídas na distribuição da ferramenta, ou então usar uma das ligações disponíveis para linguagens de programação como o Perl ou o Python.

O RRDtool está disponível em todas as distribuições de Linux. Por exemplo para o Debian, ou Kubunto basta fazer o seguinte para instalar o pacote:

# apt-get install rrdtool

A documentação disponibilizada na distribuição do RRDtool é de muito boa qualidade e está disponível através do comando 'man', em texto simples, em html, etc. Como o RRDtool tem muitas opções o comando principal 'rrdtool' admite uma série de sub-comandos. Para saber quais os comandos disponíveis basta fazer:

$ rrdtool help
RRDtool 1.2.19  Copyright 1997-2007 by Tobias Oetiker 
               Compiled May 22 2007 13:48:39

Usage: rrdtool [options] command command_options

Valid commands: create, update, updatev, graph, dump, restore,
                last, lastupdate, first, info, fetch, tune,
                resize, xport

RRDtool is distributed under the Terms of the GNU General
Public License Version 2. (www.gnu.org/copyleft/gpl.html)

For more information read the RRD manpages

(Assinalei os sub-comandos a azul.)

Para obter ajuda sobre o sub-comando específico fazer 'man rdd<sub-comando>'. Para ler um guia do programa fazer 'man rrdtutorial'. É claro que se pode também consultar a home page do programa onde toda a informação também está disponível.

Criação da base de dados

Vamos imaginar que queremos fazer um gráfico com a carga do sistema, onde seja possível mostrar as variações das últimas 24 horas. Esta carga pode-se obter de várias formas diferentes. Tradicionalmente o valor da carga do sistema é apresentado em média para o último minuto, para os últimos 5 minutos e para os últimos 15 minutos.

O comando para criar base de dados pode ser:

(  i)$ rrdtool create                                \
( ii)          /arquivo/rrd/carga_sistema.rrd        \
(iii)          --start 1235667600                    \
( iv)          --step=300                            \
(  v)          DS:carga:GAUGE:600:U:U                \
( vi)          RRA:AVERAGE:0.33:1:288                \
(vii)          RRA:AVERAGE:0.5:4:504

Como se pode ver o comando é mais parecido a uma pequena linguagem de programação do que a um comando normal. Por esta razão e para registo futuro, convém guardar o comando de criação das bases de dados num ficheiro, como um shell script.

O que este comando faz, passo a passo é:

  1. Nesta linha invocamos o sub-comando para criar uma base de dados.
  2. Indicamos agora que a base de dados deverá ser criada em /arquivo/rrd/carga_sistema.rrd. Por razões obvias convém termos um lugar no sistema para armazenar estas bases de dados. Isto depois facilita o processo de automação de backup.
  3. Na segunda linha indicamos a data e hora da primeira recolha de dados. Esta data vem em segundos desde 1970-01-01 00:00:00 UTC (época unix). Para obtermos o tempo corrente neste formato basta fazer:
    $ date +"%s"
  4. Aqui indica-se a cadencia das leituras, ou resolução da base de dados. Neste caso é 300 segundos (5 minutos). Este é o valor por omissão, pelo que esta linha poderia ter sido omitida.
  5. Esta linha já é mais complexa. Indicamos uma 'fonte de informação' (Data Source). O conteúdo da linha decifra-se da seguinte forma:
    • DS - damos a indicação que vamos definir a seguir uma fonte de informação;
    • carga - este vai ser o identificador pelo qual poderemos depois aceder aos dados;
    • GAUGE - aqui indica-se qual o tipo de informação que vamos armazenar, no caso, 'GAUGE' armazena valores que aumentem e diminuam com o tempo (como ó o caso da carga do sistema). O RRDtool admite outros tipos de fonte de dados, por exemplo se escolhermos 'COUNTER' isso quer dizer que os dados aumentam sempre, como num contador de horas de uma máquina, ou o número de bytes recebidos por uma interface de rede;
    • 600 - é o chamado 'heartbeat', determina o número máximo de segundos entre duas leituras da fonte de dados após os quais o valor desta fonte de dados se admite ser desconhecida. Neste caso escolhemos 10 minutos;
    • Finalmente os últimos dois valores indicam respectivamente o valor mínimo e máximo fora dos quais não deve ser considerada a leitura. Usamos a letra 'U' para denotar que não temos nem mínimo, nem máximo.

    Para cada base de dados podemos ter múltiplas fontes de informação, basta acrescentar linhas como estas tendo o cuidado de ir escolhendo nomes diferentes para cada fonte. O tipo de informação não tem de ser idêntico para cada fonte. De facto cada fonte não necessita de ter nada a ver com a anterior.

    Consultar a 'man page' rrdcreate para uma descrição completa de todas as opções possíveis nesta linha;

  6. Esta linha e a seguinte definem os arquivos que vamos ter dentro da base de dados. Cada uma destas linha define um arquivo. Um arquivo não é mais do que uma colecção de valores. Se tivermos múltiplas fontes de informação, os arquivos vão sempre conter os valores de todas as fontes de informação, ie, não é possível especificar para uma fonte de informação leituras durante 24 horas de 5 em cinco minutos e para outra especificar outro período de tempo e cadência de leituras.

    Atenção que na função para desenho dos gráficos podemos especificar fontes de informação de bases de dados diferentes, pelo que será essa a forma ideal de termos especificações diferentes dos arquivos para fontes de informação diferentes.

    Esta linha decifra-se da seguinte forma:

    • RRA - indicamos que vamos definir um arquivo da base de dados (Round Robin Archive);
    • AVERAGE - esta é a função de consolidação dos dados. Recebemos dados de 'step' em 'step' segundos, no nosso caso de 300 em 300 segundos (pontos de informação primários). Se neste arquivo armazenarmos uma leitura de 600 em 600 segundos, vamos tirar a média desses dois pontos para armazenar um ponto deste ficheiro. As outras funções de consolidação disponíveis são MAX, MIN e LAST (última leitura);
    • O valor a seguir a AVERAGE indica a percentagem de pontos primários que podem ser 'desconhecidos' e apesar disso tiramos o valor consolidado. Neste caso escolhemos 0.33, ou seja 33% das leituras podem ser desconhecidas;
    • Número de 'steps' que devemos esperar até armazenarmos no arquivo o valor da leitura (modificado pela função de consolidação). Neste caso escolhemos 1, ou seja a cada 300 segundos armazenamos uma leitura;
    • O último valor da linha define quantas leituras vamos armazenar. Neste caso temos 288 leituras, feitas de 5 em 5 minutos (24 horas).
  7. Nesta última linha definimos outro arquivo, usando também a função de consolidação AVERAGE. Tiramos as médias, mesmo que nos faltem 50% das leituras entre pontos do arquivo. É acrescentada uma leitura ao arquivo a cada 4 'steps' ou seja de 20 em 20 minutos, até 504 vezes, ou seja uma semana (20*504/60/24=7dias). Este arquivo vai ser útil para traçarmos o gráfico da variação da carga ao longo de uma semana. Se o gráfico tiver 500 pixels, ficamos com uma resolução mais ou menos igual no gráfico e no arquivo.

Recolha dos dados

Continuando o exemplo, o primeiro problema a resolver vai ser a recolha dos dados. Isso pode-se fazer de várias formas, usando as ferramentas tradicionais do unix (awk, cut, etc), ou usando qualquer outra ferramenta. Por exemplo com usando um shell script com um bocadinho de python à mistura, ficamos com:

#!/bin/sh

CARGA=`uptime | python -c "import sys; print sys.stdin.read().split()[-2][:-1]"`
HORA=`date +"%s"`

rrdtool update /arquivo/rrd/carga_sistema.rrd $HORA:$CARGA

O sub-comando 'update' é muito mais simples que o 'create'. Mesmo assim, podemos complicar um bocadinho mais se tivermos várias fontes de informação (DS). Se tivermos, por exemplo várias fontes de informação o comando ficaria:

rrdtool update <base de dados> <tempo>:<valor fonte 1>:<valor fonte 2>:etc...

A ordem das fontes de informação será a mesma ordem pela qual foi criada a base de dados. Se não quisermos usar esta ordem, podemos especificar directamente a ordem usando a opção '--template'.

Finalmente, podemos introduzir várias leituras de uma vez, na mesma linha de comando:

rrdtool update <base de dados> \
    <tempo 1>:<valor fonte 1>:<valor fonte 2>:etc... \
    <tempo 2>:<valor fonte 1>:<valor fonte 2>:etc... \
    etc... 

Resta-nos automatizar a invocação deste script a cada 5 minutos, para tal basta editar o crontab:

$ crontab -e

E acrescentar a linha:

*/5 * * * * /arquivo/scripts/update_rdd

(Assumindo que o script acima foi gravado em '/arquivo/scripts/update_rdd' e tornado executável.)

Criar os gráficos

Tal como o comando para criar a base de dados, o comando para criar gráficos é também ele muito complicado. A documentação completa deste comando compreende:

Para o exemplo da carga do sistema, qualquer coisa como o seguinte bastaria:

(  i)rrdtool graph                                              \
( ii)    /arquivo/rrd/carga_sistema.png                         \
(iii)    --title "Carga do sistema nas ultimas 24 Horas"        \
( iv)    DEF:carga=/arquivo/rrd/carga_sistema.rrd:carga:AVERAGE \
(  v)    AREA:carga#e4a25e LINE2:carga#5e0710:"Carga"

Este comando gera o gráfico seguinte:

  1. Sub comando para criação de gráficos;
  2. Indicamos qual o nome do ficheiro a criar. Podemos escolher extensões 'png' ou 'gif' que serão reconhecidas automaticamente. Podemos também usar o caracter '-' em cujo o caso o gráfico é escrito para o stdout em formato 'gif';
  3. Definição do título do gráfico;
  4. Definição das fontes de dados a utilizar, tem este formato:
    DEF:nome_var=fich_rrd:fonte_informação:função consolidação[:step=step][:start=tempo][:end=tempo]
    • DEF - Cada gráfico tem de ter no mínimo uma fonte de dados;
    • Nome Variável - que vai ser usado para desenhar o gráfico;
    • Ficheiro RRD - com a base de dados;
    • Fonte de Informação - dentro da base de dados referida anteriormente, qual é a fonte de informação que vamos associar à variável;
    • Função de consolidação - O gráfico vai ter uma resolução própria, que é função das dimensões do próprio gráfico. Assim é quase garantido termos de consolidar de alguma forma a informação extraída da base de dados para a puder mostrar no gráfico. Aqui define-se qual a função usada para fazer essa consolidação;
    • A partir daqui os parâmetros são opcionais e auto-explicativos. Podemos indicar o tempo inicial e final para o qual consideramos esta fonte de informação, e além disso também podemos indicar a resolução em que se vai consolidar a informação, com o parâmetro step.

    Notar que esta linha apenas torna disponível a fonte de informação às funções que vão desenhar o gráfico.

  5. Nesta linha damos a ordem para desenho do gráfico. Na realidade damos duas ordens para conseguir isso, na primeira desenhamos um gráfico tipo 'área' com a cor #e4a25e e a seguir desenhamos, usando a mesma variável, um gráfico tipo linha com a cor #5e0710 - com isto consegue-se o efeito de rebordo apresentado. Podemos apresentar tantas fontes de informação quantas as que quisermos, basta ir acrescentando ordens como estas.

    O formato para criar o gráfico é:

    <Tipo de gráfico>:<nome da variável>[#cor][:[legenda][:STACK]]
    • Tipo de gráfico - os tipos de gráficos disponíveis são AREA e LINE<espessura>. Notar que existem vários comandos adicionais que permitem escrever para o gráfico (ver 'man rrdgraph_graph');
    • Nome da variável - variável definida numa declaração 'DEF' ou calculada de outro modo com as declarações CDEF ou VDEF;
    • A cor é opcional (bem como o resto das opções), trata-se de cor de 32bits como a que é utilizada nas páginas HTML;
    • Se indicarmos legenda esta aparece no rodapé do gráfico;
    • E finalmente se a opção 'STACK' for incluída, o elemento a ser desenhado será empilhado por cima da declaração LINE ou AREA anterior.

Não especificámos o tempo inicial e final para construir este gráfico, isto porque, por omissão, são desenhadas as últimas 24Horas. Se quisermos especificar o inicio do gráfico, basta usar a opção '--start=<tempo inicial>' e para especificar o fim a opção '--end=<tempo final>'. Em ambos os casos os tempos devem ser dados em segundos desde 1970-01-01 00:00:00 UTC. Por exemplo para calcularmos a última semana, podemos usar:

AGORA=`date +"%s"`
ULTIMASEMANA=$(($AGORA - 3600*24*7))

Notas sobre fontes de dados calculadas

Podemos criar fontes de dados a partir de variáveis já existentes. Imaginemos que tínhamos um serviço de transferência de ficheiros (que é útil ter para transferir documentos volumosos entre filiais de uma empresa). No nosso site interno vamos armazenando as estatísticas numa base de dados 'round robin'. Um gráfico para apresentar o tráfego poderá ser qualquer coisa como:

rrdtool graph                                                   \
    /arquivo/rrd/teste.png                                      \
    --title "Tipo de uploads"                                   \
    DEF:nfotos=/arquivo/rrd/estatistica_site.rrd:nfotos:AVERAGE \
    DEF:npdf=/arquivo/rrd/estatistica_site.rrd:npdf:AVERAGE     \
    LINE2:nfotos:"Fotos recebidas"                              \
    LINE2:npdf:"Arquivos PDF"

Se quisermos mostrar o total de ficheiros transferidos, podemos usar criar uma fonte de dados, por exemplo com:

   CDEF:total=nfotos,npdf,+

Notar que se utiliza a notação polaca reversa para fazer esta operação. A explicação desta notação sai fora do âmbito deste artigo. Esta notação é bastante familiar para quem utiliza máquinas de calcular cientificas da HP. Em geral começa-se por indicar os argumentos da função e no fim a função a calcular (neste caso uma adição simples). Por exemplo:

A seguir podemos traçar em gráfico esta variável:

rrdtool graph                                                    \
     /arquivo/rrd/teste.png                                      \
     --title "Tipo de uploads"                                   \
     DEF:nfotos=/arquivo/rrd/estatistica_site.rrd:nfotos:AVERAGE \
     DEF:npdf=/arquivo/rrd/estatistica_site.rrd:npdf:AVERAGE     \
     LINE2:nfotos:"Fotos recebidas"                              \
     LINE2:npdf:"Arquivos PDF"                                   \
     CDEF:total=nfotos,npdf,+                                    \
     AREA:total#accff5:"Total Geral"

Conclusão

O RRDtool é uma ferramenta valiosíssima na interpretação dos dados produzidos num sistema. Permite-nos identificar tendências imediatamente e actuar de forma preventiva. Se tivermos sensores externos podemos usar o RRDtool para representar uma gama enorme de fenómenos.

25.02.2009 | Ler mais | Comentários | Tags ,

Voltar à Página principal | Made with PyBlosxom