19
Departamento de Informática UM MECANISMO DE DEPURAÇÃO PARA SISTEMAS DISTRIBUÍDOS Aluno: Carla Galdino Wanderley Orientador: Arndt von Staa Introdução O termo qualidade de software é relativo: considere um sistema web que apresente uma falha por semana e esta provoque a sua reinicialização. Se este for um sistema de missão- crítica ele será considerado de baixa qualidade, entretanto, se for um simples sistema de gestão de informações a sua qualidade ainda poderá ser considerada como média ou até mesmo alta. Qualidade pode ser definida como um conjunto de propriedades e características de um produto ou serviço a serem satisfeitas em determinado grau, e que lhe confere a capacidade de satisfazer as necessidades explícitas e implícitas de seus usuários e clientes. No caso de software a avaliação de qualidade pode ser realizada a partir de um conjunto de atributos definidos de acordo com a norma [ISO 9126], que são: usabilidade, funcionalidade, confiabilidade, eficiência, manutenibilidade e portabilidade. Ainda que a qualidade seja uma propriedade multidimensional, dentro do contexto de sistemas de missão-crítica, consideramos a confiabilidade um atributo chave, pois neste tipo de sistema é esperado que o número de ocorrências de falhas seja ínfimo. Outro atributo considerado neste contexto é a disponibilidade do software, que se refere à probabilidade de um sistema funcionar satisfatoriamente sempre que solicitado. Além disso, sabemos que é importante focar no desenvolvimento de software que se aproxime a ser fidedigno por construção, pois cerca de 50% do software posto em uso contém defeitos não triviais [Boehm and Basili 2001] e ainda dependemos excessivamente de software que frequentemente falha de forma imprevisível [Pitac 1999]. Outro ponto a ser considerado é que estas métricas são feitas considerando todo tipo de software. A qualidade pode ser comprometida a despeito dos esforços dos desenvolvedores, pois foi verificado que as bibliotecas de classes são frequentemente não confiáveis [Thomas 2002]. Considerando que o objetivo do nosso trabalho é produzir mecanismos para aumentar a qualidade do software, optamos por investir em ferramentas que aumentem os atributos confiabilidade e disponibilidade. Acreditamos que a partir da criação de mecanismos de introspecção seja possível criar ferramentas para humanos (depuradores) e máquinas (sistemas orientados à recuperação), em ambos os casos auxiliando a compreensão do sistema e, consequentemente, reduzindo o tempo médio de reparo (MTTR) quando uma falha for encontrada, logo contribuindo para a melhoria da qualidade em virtude da maior facilidade de remoção de eventuais defeitos. Este relatório está dividido da seguinte forma: na seção 1 introduzimos o assunto; na seção 2 apresentamos as motivações para esta pesquisa; na seção 3 discutimos o estado da arte atual; na seção 4 apresentaremos o mecanismo de depuração; na seção 5 discutimos as contribuições esperadas; na seção 6 apresentamos um esboço da solução; e por fim, na seção 7 descrevemos o cronograma.

UM MECANISMO DE DEPURAÇÃO PARA SISTEMAS DISTRIBUÍDOS · Departamento de Informática al 2009]. Ambos promovem extensões para a linguagem C++, mas D³S utiliza uma linguagem de

  • Upload
    others

  • View
    2

  • Download
    0

Embed Size (px)

Citation preview

Page 1: UM MECANISMO DE DEPURAÇÃO PARA SISTEMAS DISTRIBUÍDOS · Departamento de Informática al 2009]. Ambos promovem extensões para a linguagem C++, mas D³S utiliza uma linguagem de

Departamento de Informática

UM MECANISMO DE DEPURAÇÃO PARA SISTEMAS

DISTRIBUÍDOS

Aluno: Carla Galdino Wanderley

Orientador: Arndt von Staa

Introdução

O termo qualidade de software é relativo: considere um sistema web que apresente uma

falha por semana e esta provoque a sua reinicialização. Se este for um sistema de missão-

crítica ele será considerado de baixa qualidade, entretanto, se for um simples sistema de

gestão de informações a sua qualidade ainda poderá ser considerada como média ou até

mesmo alta.

Qualidade pode ser definida como um conjunto de propriedades e características de um

produto ou serviço a serem satisfeitas em determinado grau, e que lhe confere a capacidade de

satisfazer as necessidades explícitas e implícitas de seus usuários e clientes. No caso de

software a avaliação de qualidade pode ser realizada a partir de um conjunto de atributos

definidos de acordo com a norma [ISO 9126], que são: usabilidade, funcionalidade,

confiabilidade, eficiência, manutenibilidade e portabilidade.

Ainda que a qualidade seja uma propriedade multidimensional, dentro do contexto de

sistemas de missão-crítica, consideramos a confiabilidade um atributo chave, pois neste tipo

de sistema é esperado que o número de ocorrências de falhas seja ínfimo. Outro atributo

considerado neste contexto é a disponibilidade do software, que se refere à probabilidade de

um sistema funcionar satisfatoriamente sempre que solicitado.

Além disso, sabemos que é importante focar no desenvolvimento de software que se

aproxime a ser fidedigno por construção, pois cerca de 50% do software posto em uso contém

defeitos não triviais [Boehm and Basili 2001] e ainda dependemos excessivamente de

software que frequentemente falha de forma imprevisível [Pitac 1999]. Outro ponto a ser

considerado é que estas métricas são feitas considerando todo tipo de software. A qualidade

pode ser comprometida a despeito dos esforços dos desenvolvedores, pois foi verificado que

as bibliotecas de classes são frequentemente não confiáveis [Thomas 2002].

Considerando que o objetivo do nosso trabalho é produzir mecanismos para aumentar a

qualidade do software, optamos por investir em ferramentas que aumentem os atributos

confiabilidade e disponibilidade. Acreditamos que a partir da criação de mecanismos de

introspecção seja possível criar ferramentas para humanos (depuradores) e máquinas

(sistemas orientados à recuperação), em ambos os casos auxiliando a compreensão do sistema

e, consequentemente, reduzindo o tempo médio de reparo (MTTR) quando uma falha for

encontrada, logo contribuindo para a melhoria da qualidade em virtude da maior facilidade de

remoção de eventuais defeitos.

Este relatório está dividido da seguinte forma: na seção 1 introduzimos o assunto; na

seção 2 apresentamos as motivações para esta pesquisa; na seção 3 discutimos o estado da arte

atual; na seção 4 apresentaremos o mecanismo de depuração; na seção 5 discutimos as

contribuições esperadas; na seção 6 apresentamos um esboço da solução; e por fim, na seção

7 descrevemos o cronograma.

Page 2: UM MECANISMO DE DEPURAÇÃO PARA SISTEMAS DISTRIBUÍDOS · Departamento de Informática al 2009]. Ambos promovem extensões para a linguagem C++, mas D³S utiliza uma linguagem de

Departamento de Informática

Motivação

A geração de informações de introspecção, ou seja, a observação do funcionamento do

software feita pelo próprio software, é uma atividade bastante utilizada durante o

desenvolvimento de sistemas complexos. Esta atividade promove o aumento do volume de

informações relacionadas ao sistema, que podem ser utilizadas tanto por desenvolvedores

quanto administradores com o objetivo de diagnosticar eventuais falhas.

Uma técnica comum neste contexto é a produção de logs com mensagens que

descrevam o comportamento do sistema em tempo de execução, podendo conter valores

associados que auxiliem a contextualizar as informações. Esta técnica é bastante interessante

pois aumenta o conhecimento sobre o funcionamento do sistema e fornece informações com

muita riqueza de detalhes acerca do sistema em execução. Entretanto, a utilização desta

técnica demanda muito esforço por parte dos desenvolvedores do sistema e seus resultados

nem sempre são satisfatórios quando aplicados a sistemas reais, já que o volume de dados

gerados pelos logs tende a ser muito grande. Assim como o volume a organização dos logs é

um ponto importante a ser considerado, pois uma estruturação ruim de eventos de log pode

reduzir a visibilidade das informações relevantes para o problema.

Além disso, a dificuldade de utilização de logs cresce exponencialmente quando

tratamos de ambientes distribuídos, pois neste contexto, os logs ficam espalhados em

diferentes máquinas ou dispositivos. Isto faz com que seja necessário acessá-los um a um para

inspeção, acrescentando mais uma dificuldade ao processo inicial: a ordenação global de

todos os eventos capturados em todas as máquinas.

Como o conhecimento sobre o sistema é um ponto importante para a nossa solução,

consideramos a técnica de geração de logs adequada para a solução do problema. Dessa

forma, apresentamos um mecanismo de depuração para sistemas distribuídos composto por

uma biblioteca que auxilia a geração de informações de introspecção (tendo como base o log

de execução do sistema) e um sistema de visualização para estudar o comportamento do

sistema como um todo a partir deste log.

Estado da Arte

Existem várias abordagens relacionadas à depuração de sistemas distribuídos. Uma

delas é a verificação de modelos [Killian et al 2007], que utiliza verificadores baseados nas

especificações do sistema para encontrar estados inconsistentes. O trabalho de Killian [Killian

et al 2007] especificamente fornece mecanismos para identificar estados suspeitos do sistema

e uma ferramenta para reexecutá-lo de forma interativa. Esta ferramenta é baseada em uma

máquina virtual com controles para voltar ou avançar a execução, permitindo que o

desenvolvedor estude o comportamento do sistema em cada ponto da execução. Esta

abordagem pode ser poderosa para o processo de depuração, no entanto, para detectar estados

suspeitos, assume-se que a especificação seja corretamente implementada além dela própria

estar correta do ponto de vista formal. Outra desvantagem desta abordagem é a dependência

de um ambiente virtualizado para reproduzir a falha.

Uma segunda abordagem seria a verificação baseada em reprodução, que disponibiliza

ao programador a capacidade de reprodução da execução de um programa, mimetizando sua

ordem e ambiente. Como exemplo de trabalho baseado nesta abordagem, temos Liblog [Geels

et al 2007]. Esta biblioteca cria logs durante a execução de um sistema e promove um

“replay” deterministicamente. O grande benefício deste tipo de ferramenta é a capacidade de

reprodução de falhas de forma consistente, mas por outro lado, possui um custo bastante

elevado de registro e reprodução de uma execução inteira.

Outra abordagem possível é a criação de depuração e verificação automatizada. Esta

abordagem promove o uso de predicados e representação destes predicados em grafos de

fluxo de dados. Como exemplo desta abordagem, temos D³S [Liu 2008] e MaceODB [Dao et

Page 3: UM MECANISMO DE DEPURAÇÃO PARA SISTEMAS DISTRIBUÍDOS · Departamento de Informática al 2009]. Ambos promovem extensões para a linguagem C++, mas D³S utiliza uma linguagem de

Departamento de Informática

al 2009]. Ambos promovem extensões para a linguagem C++, mas D³S utiliza uma linguagem

de scripts além destas extensões. Esta abordagem pode ser eficaz, já que verifica

automaticamente estados de um sistema distribuído como um todo, mas diminui bastante o

desempenho das aplicações que a utilizam por conta do “overhead” referente às verificações.

Por fim, temos a depuração através de logs, categoria em que a solução aqui proposta

se encaixa. Este tipo de abordagem promove a geração de informações para a análise de

registros pós-execução. Um exemplo desta metodologia é Pip [Reynolds et al 2006]. Pip

possibilita aos programadores especificar expectativas acerca da estrutura do sistema, assim

como outras propriedades, gerando logs para o sistema e, além disso, fornece uma interface

visual para explorar comportamentos normais e anormais. O mecanismo apresentado difere de

Pip na estrutura de criação de logs, que é organizada de forma a facilitar a busca de

informações conforme o contexto desejado. Esta estrutura de logs também ajudou na criação

da ferramenta de visualização destes logs, visando auxiliar a disposição de dados relevantes.

A maioria das ferramentas de auxílio à analise de logs do sistema, como é o caso de Pip,

necessitam da definição de estados inconsistentes do sistema para que seja possível analisar

informações sobre a execução. No entanto, acreditamos que é importante disponibilizar estas

informações de uma forma fácil, visando aumentar o conhecimento sobre o sistema mesmo

sem a identificação de falhas.

O mecanismo de depuração

O mecanismo de depuração apresentado tem como objetivo principal auxiliar o

desenvolvimento de sistemas distribuídos, disponibilizando informações inerentes ao software

em execução, sendo estas produzidas por instrumentação contida no código ou mesmo

coletadas automaticamente, como por exemplo, dados disponíveis a partir de medições

realizadas na plataforma. Estas informações devem ser disponibilizadas permitindo uma

forma de visualização, criada especialmente para a depuração de sistemas distribuídos. É

importante que esta forma de visualização seja estruturada com base nas necessidades dos

desenvolvedores, facilitando o processo de busca e identificação de possíveis falhas.

Dessa forma, criamos um mecanismo de depuração que utiliza informações de introspecção

do sistema-alvo para apresentar o seu comportamento em tempo de execução sob a forma de

eventos ordenados cronologicamente, ainda possibilitando a sua seleção conforme as

necessidades de cada operação de depuração. Isso é feito através de filtros que possibilitam a

inclusão e exclusão de eventos, baseando-se nas suas meta-informações.

Arquitetura

O mecanismo de depuração apresentado é baseado em informações de introspecção

referentes aos componentes de um sistema distribuído. Portanto, é necessário que estas

informações sejam obtidas facilmente e que estejam disponíveis para que os desenvolvedores

as consultem.

Dessa forma, projetamos a arquitetura do mecanismo de uma forma abstrata, seguindo

o fluxo de informações. As informações são originadas em cada um dos componentes do

sistema distribuído e enviadas a um servidor central. O servidor realiza algumas rotinas de

tratamento nas informações recebidas e logo em seguida, as armazena em um banco de dados.

Neste momento, estas informações se tornam disponíveis para os usuários do mecanismo,

através de uma ferramenta de visualização. O fluxo de dados foi representado na figura a

seguir:

Page 4: UM MECANISMO DE DEPURAÇÃO PARA SISTEMAS DISTRIBUÍDOS · Departamento de Informática al 2009]. Ambos promovem extensões para a linguagem C++, mas D³S utiliza uma linguagem de

Departamento de Informática

Figura 1 - Fluxo de informações originado pela utilização do mecanismo de depuração

O fluxo de dados acima nos apresenta três pontos a serem considerados: (1) Como gerar

informações de contexto nos componentes do sistema; (2) Como armazenar o grande volume

de dados originados e (3) Como apresentar as informações de maneira adequada para o

processo de depuração.

Considerando os pontos apresentados, definimos uma solução que consiste na criação de uma

biblioteca de auxílio à coleta de informações de introspecção, um servidor de tratamento e

armazenamento das informações coletadas e uma ferramenta de apoio à inspeção.

Figura 2 – Desafios e soluções apresentadas para a depuração de sistemas distribuídos

Page 5: UM MECANISMO DE DEPURAÇÃO PARA SISTEMAS DISTRIBUÍDOS · Departamento de Informática al 2009]. Ambos promovem extensões para a linguagem C++, mas D³S utiliza uma linguagem de

Departamento de Informática

O diagrama arquitetural da solução pode ser visto a seguir:

Figura 3 - Arquitetura do mecanismo de depuração

O diagrama acima apresenta as classes existentes em cada um dos componentes do sistema.

Considerando a solução apresentada anteriormente, os dispositivos utilizam uma biblioteca de

apoio à geração de informações de contexto. A hierarquia de classes da biblioteca está

representada na caixa azul à esquerda do diagrama. Neste contexto são encontradas as classes

Tag, Event, Stack e Logger. A classe Tag é uma estrutura de dados que possui duas

informações principais: key e value. A classe Event é composta por um conjunto de elementos

do tipo Tag, que representam informações de contexto do software. A classe Logger possui

uma pilha de Tags representada pela classe Stack. A pilha de Tags presente na classe Logger

representa o contexto corrente de execução do software. A classe Logger é responsável pelo

controle da pilha de Tags e pela notificação de eventos, representados pelos seguintes

métodos respectivamente: pushTag, popTag e notifyEvent. O método notifyEvent é

responsável pelo envio de eventos de log para um servidor central, que está representado

como o componente central do diagrama.

O servidor central é responsável pela manipulação e armazenamento de eventos de

log. A hierarquia de classes deste componente está expressa na caixa azul central e apresenta

as classes Database e EventProcess. A classe Database fornece métodos que facilitam tanto a

inserção de eventos na base de dados quanto a execução de filtros para a obtenção de eventos.

A classe EventProcess é responsável pelo tratamento de informações. O método process_logs

recebe dados enviados pelos dispositivos através de requisições, faz algumas correções e os

insere no banco de dados na forma de eventos. Os métodos get_event_list_by_interval,

count_event_list_by_interval e get_event_list_by_filters são utilizados pelo componente

representado pela ferramenta de inspeção. Estes métodos promovem a obtenção de eventos do

banco de dados e realizam algumas alterações que facilitam sua apresentação na ferramenta.

O componente Ferramenta de inspeção se resume à interface gráfica de apresentação

de eventos. Como esta interface foi desenvolvida utilizando HTML [Graham 1995],

Javascript [Powell, T., Schneider, F., 2001], AJAX [Powell, T. 2008] e JSON [Crockford, D.

2012], ela não é orientada a objetos, mas possui estrutura procedural.

Page 6: UM MECANISMO DE DEPURAÇÃO PARA SISTEMAS DISTRIBUÍDOS · Departamento de Informática al 2009]. Ambos promovem extensões para a linguagem C++, mas D³S utiliza uma linguagem de

Departamento de Informática

Aplicação de Avaliação

Tendo em vista que a utilização de um mecanismo de depuração para sistemas distribuídos

torna-se interessante apenas quando pode ser avaliado, escolhemos uma solução de cardápio

digital implementada como um sistema distribuído para implantação do mecanismo

apresentado. O sistema de cardápio digital é um sistema real que utiliza tablets para

apresentação de dados e um sistema web para gerenciamento.

O aplicativo executado no tablet é baseado em uma linha de produto [Clements e Northrop

2002] e, durante a configuração de cada cliente, é produzido um layout customizado seguindo

a identidade visual da sua marca, de acordo com a escolha prévia dos ativos (assets) da linha

de produto. Além da escolha dos assets existe uma configuração fina dos mesmos, realizada

através de arquivos de configuração. O layout é produzido é sensível à escolha dos assets e

das configurações definidas. A aplicação web de gestão do conteúdo permite inserir, editar e

remover diferentes tipos de produtos, além de fornecer mecanismos para configurar o

aplicativo dos tablets.

O servidor de sincronização é responsável pela atualização incremental do conteúdo e das

configurações dos tablets.

A escolha deste sistema como estudo de caso se adéqua-se perfeitamente ao presente trabalho

devido às dificuldades identificadas em seu ambiente de produção, que se deve

principalmente ao trabalho concorrente de diferentes tipos de atores sobre as informações de

um mesmo cliente. De forma resumida, os atores do sistema são: um administrador

configurando a linha de produto de cada cliente segundo suas necessidades, uma equipe de

catalogação inserindo a ficha técnica de produtos requisitados pelos clientes e uma equipe de

designers produzindo o layout segundo as especificações de cada cliente. E importante deixar

claro que o trabalho realizado por estes atores não é restrito a etapa inicial de implantação do

sistema, mas persiste ao longo da sua utilização.

Neste contexto, podemos identificar as entidades do sistema descrito. Dessa forma, tanto a

instância do aplicativo de cartas digitais executada em cada iPad quanto as instâncias

resultantes da utilização do sistema de gerenciamento são componentes do sistema-alvo.

Portanto, ele se encaixa na definição de um sistema distribuído e pode ser considerado para a

avaliação do mecanismo apresentado.

Geração de informações de contexto

O mecanismo apresentado consiste na depuração de sistemas distribuídos com base em seu

contexto de execução. Um processo normalmente utilizado na depuração de sistemas

distribuídos é a utilização de logs, que permitam a inspeção de informações sobre a execução

de cada componente do sistema.

Esta abordagem pode funcionar bem em alguns casos, mas na maioria das vezes gera uma

quantidade de dados muito grande, com informações que intercalam semânticas diferentes a

respeito do sistema. Estes problemas acabam dificultando o processo de depuração, uma vez

que se torna necessário que o depurador aplique filtros sobre este conjuntos de dados,

tentando inferir algum padrão nos logs emitidos pelos componentes.

Page 7: UM MECANISMO DE DEPURAÇÃO PARA SISTEMAS DISTRIBUÍDOS · Departamento de Informática al 2009]. Ambos promovem extensões para a linguagem C++, mas D³S utiliza uma linguagem de

Departamento de Informática

Considerando os problemas apresentados, percebemos que a manipulação destes logs seria

muito mais eficaz caso os dados fossem estruturados a fim de facilitar a depuração. Como

consequência, projetamos uma estrutura para a geração de logs de sistema que tem como

unidade principal o evento.

Um evento é um conjunto de informações referentes a um momento da execução de um

sistema ou componente adicionadas a uma mensagem que descreve de forma textual o

procedimento que está sendo realizado. Dessa forma, um evento pode representar a

arquitetura do sistema, o método corrente, a pilha de execução e ao mesmo tempo, fornecer

informações de mais alto nível através de sua mensagem.

Biblioteca de apoio à introspecção

A estratégia escolhida para obtenção de informações de introspecção foi criar uma biblioteca

para cada linguagem a ser utilizada, que auxiliasse a geração e a notificação de eventos.

Projetamos uma solução que se assemelha a utilização de um log tradicional dispondo

mensagens textuais, porém, com a adição de informações do contexto de execução, que

obedecem um formato bem definido: uma lista de Tags com Chave e Valor. A técnica

utilizada permite que os logs sejam escritos no lugar de comentários, o que diminui o esforço

necessário para a instrumentar o código.

Adicionalmente, a própria biblioteca gera automaticamente outras informações de contexto, a

fim de complementar as informações já fornecidas. As informações geradas também são

dispostas como uma lista de Tags nome-valor. Como exemplo, apresentamos a seguir um

evento neste formato:

[dateTime:2012-05-25 10:15:23] [container:RobotAPI] [component:UTSensor]

[action:ReadSensorData] [failure] Não foi possível estabelecer a comunicação com a

eletrônica.

Este evento está expressando a mensagem Não foi possível estabelecer a comunicação com a

eletrônica, que está associada às Tags dateTime, container, componente, action e failure com

seus respectivos valores 2012-05-25 10:15:23, RobotAPI, UTSensor, ReadSensorData e sem

valor para a última Tag. A primeira Tag representa o momento exato em que a mensagem foi

gerada, a qual é embutida pela biblioteca. Já a segunda e terceira representam o contexto

arquitetural do sistema, a quarta representa o contexto em que ela foi emitida (nome de

método) e a última indica que ela foi uma falha. Neste caso, as quatro últimas seriam

informadas pelo desenvolvedor.

Existem algumas informações que são relevantes para expressar o contexto de aplicações em

geral, outras ainda são importantes para marcar eventos relacionados a estados inconsistentes

dos sistemas. Dessa forma, listamos algumas Tags que podem ser utilizadas no processo de

instrumentação:

- Error - Indica uma falha no sistema.

- Disaster – Indica uma falha que causa um dano irrecuperável.

Page 8: UM MECANISMO DE DEPURAÇÃO PARA SISTEMAS DISTRIBUÍDOS · Departamento de Informática al 2009]. Ambos promovem extensões para a linguagem C++, mas D³S utiliza uma linguagem de

Departamento de Informática

- Warning – Indica uma inconsistência dos dados ou uma condição suspeita.

- Environment – Define o ambiente de execução, que pode assumir valores como server ou

mobile.

- Function – Define o nome da função corrente.

- Action – Define a ação corrente dentro da execução, eu seja, a semântica da operação

corrente.

- CPU – Carga corrente de processamento.

- Memory – Memória ocupada pela aplicação.

Interface da biblioteca

Seguindo a especificação apresentada criamos uma interface sob forma de IDL [Auerbach

J.S.,Russell J.R.1994] que define os contratos a serem seguidos:

interface Tag {

attribute string key;

attribute string value;

}

typedef sequence<Tag> TagList;

interface TagDictionary {

attribute TagList tags;

}

module EventManager {

void notifyEvent(in string message);

void notifyEvent(

in string message,

in TagDictionary dict);

void pushTag(in string name);

Page 9: UM MECANISMO DE DEPURAÇÃO PARA SISTEMAS DISTRIBUÍDOS · Departamento de Informática al 2009]. Ambos promovem extensões para a linguagem C++, mas D³S utiliza uma linguagem de

Departamento de Informática

void pushTag(

in string name,

in string value);

void popTag();

}

Esta interface contém a definição de uma estrutura Tag, representada como um par chave-

valor, e uma estrutura TagList, que representa uma lista de estruturas do tipo Tag. A estrutura

TagList é utilizada como uma pilha, em que informações de contexto do software sob forma

de Tags são empilhadas e desempilhadas conforme a execução da aplicação.

Em seguida, apresentamos os métodos necessários para a geração de informações de contexto:

notifyEvent, pushTag e popTag.

Os métodos pushTag e popTag são responsáveis pela manipulação das informações de

contexto inseridas na pilha de Tags. Estes métodos devem ser utilizados em conjunto para que

não hajam inconsistências nos logs gerados.

O método notifyEvent é responsável pela criação e envio de eventos. Sua assinatura possui

alguns parâmetros, sendo o primeiro deles uma string que representa uma mensagem e o

segundo, um parâmetro opcional que representa um conjunto de Tags. Este método cria

eventos utilizando a mensagem fornecida pelo usuário e as informações de contexto contidas

na pilha de Tags, que podem ser acrescidas de outras Tags, fornecidas através do parâmetro

opcional.

Implementação

A geração de informações de contexto ocorre através de instrumentação do código do

sistema-alvo, utilizando chamadas de funções que recebem como parâmetros uma string,

representando uma mensagem e estruturas chave-valor a serem adicionadas no evento criado.

Considerando o contexto de avaliação do sistema apresentado anteriormente, podemos

verificar que os componentes apresentam conjuntos de características diferentes entre si. Uma

destas características é a linguagem utilizada por cada componente, o que influi diretamente

na criação da biblioteca de geração de informações de contexto.

Um dos principais problemas na geração de informações do contexto do software é a

dificuldade na instrumentação do código. Portanto, é importante considerar maneiras de

reduzir o esforço na execução desta tarefa. Dessa forma, optamos por gerar bibliotecas

diferentes para cada linguagem utilizada, o que nos possibilita utilizar as características de

cada linguagem para criar açúcares sintáticos que facilitem o processo de instrumentação do

código. Dessa maneira, implementamos a biblioteca apresentada para duas linguagens:

Objective-C [Cox B. 1986], e Python [Rossum, G. van 1991].

Page 10: UM MECANISMO DE DEPURAÇÃO PARA SISTEMAS DISTRIBUÍDOS · Departamento de Informática al 2009]. Ambos promovem extensões para a linguagem C++, mas D³S utiliza uma linguagem de

Departamento de Informática

Objective-c

Os componentes representados pelos iPads utilizam a plataforma iOS [Apple 2007] e tem

Objective-C [Cox B. 1986], como linguagem de desenvolvimento. Esta é uma linguagem

compilada que apresenta interoperabilidade com as linguagens C e C++.

Como dito anteriormente, a utilização dos métodos pushTag e popTag prevê cuidado

constante no processo de instrumentação, uma vez que se utilizados de forma assíncrona,

geram inconsistências nas informações de contexto que compõem os logs. Como solução para

este problema, optamos por utilizar a pré-compilação para o gerenciamento de informações de

contexto, criando macros responsáveis pelo controle da pilha de Tags.

A macro 'SCOPED_TAG' insere uma ou mais Tags na pilha de contexto e faz a remoção no

fim do escopo corrente. A utilização desta macro diminui o esforço de instrumentação do

código, uma vez que retira do programador a responsabilidade de remover as Tags no fim de

cada escopo. Como exemplo, a utilização desta macro em um método:

-(void) functionTest {

SCOPED_TAG('operation', 'test');

...

}

Como mencionado anteriormente, o método de notificação é responsável pela criação e envio

de eventos a um servidor central. No entanto, o processo de envio deve considerar algumas

características dos componentes do sistema, uma vez que optamos pela centralização de

eventos. Um ponto importante é como este processo pode ser estruturado na presença de

entidades ubíquas, como é o caso do aplicativo sendo executado nos iPads.

É importante considerar que sistemas ubíquos costumam ser mais suscetíveis a quedas de

energia. Este fato nos remete ao problema de manter eventos em memória esperando o

momento de transmissão, pois uma vez que haja uma queda de energia, as informações da

memória do dispositivo serão completamente perdidas.

Para solucionar estes problemas definimos uma política de envio de eventos a ser

implementada em bibliotecas de sistemas ubíquos. Esta política consiste no envio de

pequenos pacotes, lidos diretamente do disco em um modelo produtor-consumidor.

Cada evento criado é imediatamente gravado no arquivo corrente, e quando este arquivo

atinge um tamanho limite, é fechado e marcado para envio. Em caso de queda de luz, ao

reiniciar a aplicação, o log gerado continua sendo escrito no último arquivo. Outra

consequência desta abordagem é a garantia que em um desastre, como um acesso inválido de

memória, as informações da falha estão salvas antes da aplicação fechar.

Python

Diferentemente de Objective-C [Cox B. 1986], Python é uma linguagem interpretada,

portanto, não é possível utilizar diretivas de pré-compilação neste contexto. Porém,

Page 11: UM MECANISMO DE DEPURAÇÃO PARA SISTEMAS DISTRIBUÍDOS · Departamento de Informática al 2009]. Ambos promovem extensões para a linguagem C++, mas D³S utiliza uma linguagem de

Departamento de Informática

linguagens interpretadas fornecem outras formas de enriquecer o processo de utilização desta

biblioteca.

Assim como a implementação de Objective-C [Cox B. 1986], criamos uma forma de retirar a

responsabilidade dos programadores quanto à remoção de Tags do contexto de execução. Para

isso, utilizamos decorators de Python [Rossum, G. van 1991] que nos permitem que sejam

criados envelopes [Büchi, M., Weck W. 2000] para funções que inserem Tags de contexto

antes do método e as retiram depois dele. Dessa maneira, a chamada de uma função seria

escrita da seguinte forma:

@scoped_tag(['operation':'test'])

def functionTest:

O processo de notificação desta biblioteca é bastante simples, se comparada à solução tomada

em Objective-C [Cox B. 1986]. Uma vez que a biblioteca Python [Rossum, G. van 1991] será

utilizada em sistemas web, podemos considerar que elas possuem um alto grau de

disponibilidade. Partindo deste pressuposto, o processo de envio de informações de contexto é

realizado diretamente, pois não há necessidade de armazenamento intermediário. Assim

sendo, os eventos são enviados, um por vez, através de requisições.

Testes

As bibliotecas possuem testes automatizados. O processo de verificação da corretude consiste

na comparação entre eventos de log gerados e seus valores esperados, que são a forma

serializada dos respectivos eventos.

No caso da biblioteca para a linguagem Objective-C [Cox B. 1986], os testes automáticos não

possuem cobertura total por não considerarem o processo de envio de eventos. A criação de

testes para envio de eventos neste contexto seria difícil, uma vez que os dispositivos que

utilizam esta linguagem não possuem acesso de leitura ao servidor de armazenamento. Já a

biblioteca para a linguagem Python [Rossum, G. van 1991] pode ser testada automaticamente

em sua totalidade.

Manipulação de informações de contexto

O armazenamento de eventos é realizado em um servidor central responsável por interpretar

as informações recebidas e fazer alguns ajustes, como por exemplo, a normalização de

identificadores temporais. Considerando que cada máquina no sistema possui seu próprio

relógio, que eventualmente está diferente do relógio no servidor central, é necessário

converter os logs recebidos para o relógio do servidor central. Solucionamos este problema

enviando junto com os eventos o timestamp corrente de cada máquina, e a partir dele

calculamos o delta temporal ajustando a coerência dos relógios.

O armazenamento de eventos realizado no servidor central utiliza um banco de dados NoSQL

[Stonebraker, M. 2010] devido a forma como estruturamos o evento. Este tipo de banco de

dados armazena cada entrada em um formato de tuplas, semelhante a nossa representação de

eventos e utiliza algoritmos de busca otimizados para este tipo de estrutura. Além disso, este

Page 12: UM MECANISMO DE DEPURAÇÃO PARA SISTEMAS DISTRIBUÍDOS · Departamento de Informática al 2009]. Ambos promovem extensões para a linguagem C++, mas D³S utiliza uma linguagem de

Departamento de Informática

tipo de banco de dados pode ser distribuído, e, considerando o problema de volume de

eventos, este recurso combinado a estratégias de computação na nuvem podem resolver o

problema de uma forma simples e de baixo custo.

Inspeção do sistema-alvo

Uma vez que os eventos estejam armazenados, é necessário que possamos visualizá-los

facilmente. Porém, criar uma forma de visualização adequada pode não ser uma tarefa fácil,

uma vez que a quantidade de dados armazenados é muito grande. Portanto, é interessante que

se utilize o conhecimento prévio da estrutura das informações armazenadas de forma a propor

mecanismos de busca de informações que facilitem a vida do usuário. Seguindo esta idéia,

projetamos uma ferramenta de inspeção que permite que o usuário defina um contexto de

visualização de eventos através de conjuntos [Chave, Valor].

Ferramenta de inspeção

A ferramenta de inspeção possui um mecanismo de filtros com base na estrutura de eventos

que possibilita que sejam definidos dois conjuntos [Chave, Valor]: o conjunto de Tags que

devem estar presentes e o conjunto de Tags que não devem estar presentes em um evento para

que ele seja exibido. A ferramenta também possui os campos Desde e Até nos quais entramos

com limites para um intervalo de data e hora que funciona como um filtro temporal. Dessa

maneira, os dados são filtrados de acordo com as informações de contexto presentes nos

eventos e assim, apenas os eventos que satisfaçam ao contexto definido serão visualizados.

Assim como o número de eventos armazenados, as informações de contexto presentes nos

eventos também podem ser extensas, pois um mesmo evento pode conter informações

interessantes para diferentes perfis de depuração. Como exemplo, temos o seguinte evento:

[environment:mobile] [application:hello world] [cpu:300] [memory:1024] [flow:main]

[message:Main screen loaded]

Este evento pode ser interessante tanto para visualização de desempenho da aplicação, através

das Tags cpu e memory, quanto para a visualização do fluxo de acesso de telas do sistema.

Pensando nisso, criamos um mecanismo de configuração de visualização de Tags. Este

mecanismo nos permite definir se uma Tag será ou não visualizada ou mesmo se apenas sua

chave ou valor aparecerá. Este mecanismo permitirá que apenas as informações de contexto

relevantes para o problema em questão sejam visualizadas.

Além disso, a ferramenta de inspeção possui uma opção chamada Atualização automática que

ao ser marcada, faz com que a tela de visualização de eventos seja atualizada conforme a

chegada de novos eventos no servidor central. A atualização do conjunto de eventos

visualizados também segue o contexto de filtros definido pelos conjuntos de Tags, ou seja,

apenas eventos que chegam no servidor central e se enquadram no contexto definido pelos

filtros são adicionados à visualização. A seguir, uma imagem da ferramenta, apresentando as

funcionalidades listadas:

Page 13: UM MECANISMO DE DEPURAÇÃO PARA SISTEMAS DISTRIBUÍDOS · Departamento de Informática al 2009]. Ambos promovem extensões para a linguagem C++, mas D³S utiliza uma linguagem de

Departamento de Informática

Figura 4 - Ferramenta de apoio à inspeção

Casos de uso

A seguir, apresentamos o funcionamento da ferramenta de inspeção através de um diagrama

de casos de uso.

Figura 5 – Diagrama de casos de uso referente à ferramenta de inspeção.

Page 14: UM MECANISMO DE DEPURAÇÃO PARA SISTEMAS DISTRIBUÍDOS · Departamento de Informática al 2009]. Ambos promovem extensões para a linguagem C++, mas D³S utiliza uma linguagem de

Departamento de Informática

Funcionalidades

A seguir, forneceremos instruções para de cada componente da ferramenta da inspeção.

Filtro temporal

O filtro temporal é composto por dois campos que permitem definir limites temporais para os

eventos. A seguir, uma imagem deste filtro:

Figura 6 - Componente de filtro temporal

Data e hora devem ser fornecidas no formato yyyy-mm-dd HH:MM:SS, como pode ser visto

na imagem acima. Os botões à direta dos campos fornecem data e hora correntes nos

respectivos campos. Uma vez que as informações sejam alteradas, a aplicação do filtro deve

ser realizada com a tecla Enter.

Filtro de Tags

Este componente do sistema nos permite aplicar filtros que restringem os eventos a serem

apresentados na tela. Para utilizar este filtro é necessário fornecer uma Chave e,

opcionalmente, um valor. Em seguida, definimos se o filtro criado será para inclusão ou

exclusão de Tags através da seleção das opções Incluir ou Excluir. No caso da seleção da

opção Incluir, apenas eventos que possuem Tags com Chave e Valor fornecidos para este

filtro serão apresentadas. No caso da seleção de Excluir, eventos que possuírem Tags com

Chave e valor fornecidos serão removidas a apresentação. O campo Regex possibilita a

criação de filtros com expressões regulares para o campo Valor de Tags. Uma vez que o filtro

seja criado através do botão Inserir, ele será apresentado em uma lista de filtros logo abaixo e

poderá ser removido a qualquer momento, através do botão em forma de x que se encontra à

direta de cada elemento. A seguir, uma imagem do filtro de Tags:

Page 15: UM MECANISMO DE DEPURAÇÃO PARA SISTEMAS DISTRIBUÍDOS · Departamento de Informática al 2009]. Ambos promovem extensões para a linguagem C++, mas D³S utiliza uma linguagem de

Departamento de Informática

Figura 7 - Componente de filtro de Tags de contexto

Esta imagem apresenta a interface gráfica referente ao componente de filtro de Tags. Neste

caso, há um filtro definido com chave environment e sem valor, o que faz com sejam exibidos

apenas eventos que possuem Tags cuja chave é igual a environment.

Configurações de visualização

Este componente nos permite definir quais Tags serão apresentadas nos eventos ou mesmo se

apenas suas chaves ou valores serão apresentados. Para inserir uma configuração, basta

fornecer a chave que identifica as Tags que serão alteradas e selecionar o que se deseja

visualizar marcando apenas a opção Chave, apenas a opção Valor ou ambas. A seguir, uma

imagem do componente de configurações:

Figura 8 - Componente de configurações de visualização de Tags

Visualizador de eventos

Uma vez que filtro temporal e filtro de Tags estejam definidos, os resultados serão

apresentados em um componente de visualização de eventos. Como os eventos são

organizados através de Tags, este componente apresenta um esquema de cores que busca

associar Tags com mesma chave afim de facilitar o acompanhamento de informações de

contexto no tempo. Os eventos são organizados de forma temporal, do mais recente para o

mais antigo e seus identificadores temporais são apresentados à esquerda. À direita, temos a

mensagem de cada evento. Eventos que possuem informações adicionais possuem um botão +

à direita da mensagem, que dá acesso as informações que não estão presentes no contexto

atual. A seguir, uma imagem do componente de visualização:

Page 16: UM MECANISMO DE DEPURAÇÃO PARA SISTEMAS DISTRIBUÍDOS · Departamento de Informática al 2009]. Ambos promovem extensões para a linguagem C++, mas D³S utiliza uma linguagem de

Departamento de Informática

Figura 9 - Componente de apresentação de eventos.

Neste caso, um evento com Tag “Error” é apresentado e sua mensagem fornece informações

sobre o tipo de falha ocorrida. Este tipo de evento possuem a stackTrace como informação

adicional, que pode ser acessada através do botão à direita.

Implementação

A ferramenta de inspeção foi desenvolvida em um sistema web, portanto utilizou

conhecimentos de linguagens de estruturação e apresentação de informações, como HTML

[Graham 1995]. A dinâmica de apresentação de informações foi desenvolvida utilizando

Javascript [Powell, T., Schneider, F., 2001], AJAX [Powell, T. 2008] e Jquery [Paddock R.,

Petersen J. 2012]. O backEnd foi desenvolvido em Python [Rossum, G. van 1991] através de

um servidor Django [FORCIER, J. et al 2008] e utilizamos recursos de JSON [Crockford, D.

2012] para facilitar a transmissão de dados entre cliente e servidor.

Como estamos tratando de sistemas distribuídos que possuem componentes com baixo nível

de disponibilidade, devemos considerar que os eventos podem não estar presentes no banco

de dados quando estamos tentando identificar a causa de uma falha. Suponha que um usuário

reportou um erro e o desenvolvedor responsável pela manutenção do sistema está analisando

o contexto, mas os logs referentes a falha ainda não foram transmitidos devido a problemas de

conexão. Enquanto o desenvolvedor está estudando o comportamento do sistema, restrito

aquele cliente, a rede volta a funcionar e o dispositivo envia os logs dos seus últimos minutos

de execução. Neste momento, a visualização fica inconsistente, pois não expressa o que

realmente existe no banco de dados.

Para solucionar este problema, projetamos uma solução que consistia em refazer a busca de

eventos de acordo com os filtros configurados, para que a tela fosse reconstruída de tempos

em tempos. Entretanto, esta abordagem mostrou ser muito custosa, uma vez que além de

refazer as buscas, é necessário recriar todos os elementos da interface gráfica de acordo com

os eventos recebidos. Como consequência, projetamos uma solução de implementação

baseada na técnica Divisão e Conquista [CORMEN, T. H. et al 2000]. A solução consiste na

criação de conjuntos de eventos conforme um intervalo de tempo, cada conjunto armazena o

número de eventos que contém. A cada 5 segundos, fazemos uma requisição ao servidor de

banco de dados fornecendo os limites temporais de todos os conjuntos e obtemos como

resposta o número de eventos em cada intervalo. Neste momento, comparamos o número de

eventos do banco de dados com o número de eventos de cada intervalo apresentado na tela e

reconstruímos os intervalos inconsistentes.

Avaliação de resultados

O mecanismo de depuração desenvolvido foi implantado em um sistema real conforme

apresentado na seção Aplicação de Avaliação. Partindo deste cenário, medimos o esforço de

Page 17: UM MECANISMO DE DEPURAÇÃO PARA SISTEMAS DISTRIBUÍDOS · Departamento de Informática al 2009]. Ambos promovem extensões para a linguagem C++, mas D³S utiliza uma linguagem de

Departamento de Informática

implantação do método no sistema. O processo de instrumentação contou com dois

desenvolvedores que participaram da construção do sistema-alvo e durou cerca de dois dias.

A ferramenta de inspeção está sendo utilizada pela equipe há aproximadamente 2 semanas,

tanto para monitoramento do sistema quanto para a depuração de falhas. Até o presente

momento, apenas uma falha foi reportada para a equipe e pode ser identificada por um

desenvolvedor em aproximadamente 15 minutos. De acordo com o gerente desta mesma

equipe, era comum que falhas deste tipo necessitassem de pelo menos um dia de depuração

até que sua causa fosse identificada.

Além disso, estruturamos um estudo de caso para uma avaliação quantitativa da ferramenta.

[ARAÚJO, T. et al]

Considerações finais

Apresentamos neste trabalho um mecanismo de depuração para sistemas distribuídos baseado

em logs estruturados com informações de contexto. Estes logs são armazenados em um

servidor central e podem ser visualizados através de uma ferramenta de inspeção. O

mecanismo apresentado mostrou-se eficaz no apoio à depuração, uma vez que diminuiu o

tempo de identificação de uma falha em um sistema real.

Trabalhos futuros

Existem alguns aspectos relacionados ao trabalho apresentado que podem originar trabalhos

futuros.

O primeiro ponto a ser considerado é a distribuição do banco de dados utilizado. O banco de

dados MongoDB [MONGODB 2007] é estruturado visando sua distribuição, portanto prevê

sua organização de acordo com arquiteturas que podem não só fornecer maior confiabilidade

no armazenamento, mas também, aumentar a velocidade de acesso às informações

armazenadas.

Outro ponto a ser considerado é a implementação de mecanismos de interceptação de eventos

gerados pelo sistema operacional dos componentes, como é o caso de um acesso inválido à

memória. Este componente seria útil para o processo de instrumentação, uma vez que ajudaria

a fornecer mais informações acerca da falha ocorrida em sistemas ubíquos.

Referências

1 - ARAÚJO, T.; WANDERLEY, C.; STAA, A.V.; Um mecanismo de introspecção para depurar o

comportamento de sistemas distribuídos. In: 26º. Simpósio Brasileiro de Engenharia de Software, Natal, RN;

setembro 2012. Aceito para publicação.

2 - APPLE, (2007) iOS Disponível em: http://www.apple.com/ios/ Acesso em: 12 jun 2012

3 - AUERBACH J. S., RUSSELL J. R. (1994). The Concert signature representation: IDL as

intermediate language. In Proceedings of the workshop on Interface definition languages (IDL '94),

Jeanette M. Wing and Richard L. Wexelblat (Eds.). ACM, New York, NY, USA, 1-12.

DOI=10.1145/185084.185095 http://doi.acm.org/10.1145/185084.185095

Page 18: UM MECANISMO DE DEPURAÇÃO PARA SISTEMAS DISTRIBUÍDOS · Departamento de Informática al 2009]. Ambos promovem extensões para a linguagem C++, mas D³S utiliza uma linguagem de

Departamento de Informática

4 - BOEHM, B., BASILI, V. R. (2001). Software defect reduction top 10 list. Computer, 34:135–

137.

5 - BÜCHI, M., WECK W. (2000), ECOOP 2000 — Object-Oriented Programming – pg.201 - 225

6 - CLEMENTS, P.; NORTHROP, L.. Software Product

Lines: Practices and Patterns. Addison-Wesley, Boston, MA, EUA, (2002).

608 p.

7 - COX, J. B., NOVOBILSKI, A., (1991). Object-Oriented Programming; an Evolutionary

Approach (2nd ed.). Addison-Wesley Longman Publishing Co., Inc., Boston, MA, USA.

8 - CROCKFORD, D. (2002). Introducing JSON, Disponível em: http://www.json.org/ Acesso em:

12 jun 2012.

9 - DAO D., ALBRECHT J., KILLIAN C., VAHDAT A. (2009). Live Debugging of Distributed

Systems. Compiler Construction - pg. 94-108

10 - FORCIER, J.; BISSEX, P.; CHUN, W. (2008), Python Web Development with Django (1st

ed.), Addison-Wesley, p. 408, ISBN 0-13-235613-9, OCLC 213835556

11 - CORMEN, T. H., LEISERSON, C.E., RIVEST R. L. (2000), Introduction to Algorithms MIT

Press.

12 - GRAHAM, I. (1995). The HTML Sourcebook. John Wiley & Sons, Inc., New York, NY, USA

13 - GEELS, D., ALTEKAR, G., MANIATIS, P., ROSCOE, T., STOICA, I. (2007). Friday: Global

Comprehension for Distributed Replay. In: Proceedings of the ACM/USENIX Symposium on

Networked Systems Design and Implementation (NSDI)

14 - ISO 9126 (1991) Disponível em:

http://www.iso.org/iso/iso_catalogue/catalogue_tc/catalogue_detail.htm?csnumber=22749 Acesso

em:12 jun 2012.

15 - KILLIAN, C.E., ANDERSON, J.W., JHALA, R., VAHDAT, A. (2007). Life, Death, and the

Critical Transition: Finding Liveness Bugs in Systems Code. In: Proceedings of the

ACM/USENIX Symposium on Networked Systems Design and Implementation (NSDI)

16 - LIU, X., GUO, Z., WANG, X., CHEN, F., LIAN, X., TANG, J., WU, M., KAASHOEK, M.F.,

ZHANG, Z. (2008). D3S: Debugging Deployed Distributed Systems. In: Proceedings of the

ACM/USENIX Symposium on Networked Systems Design and Implementation (NSDI)

17 - MONGODB (2007), Disponível em: http://www.mongodb.org/ Acesso em: 12 jun 2012.

18 - PADDOCK R., PETERSON J. (2012). Practical Jquery (1st ed.). Apress, Berkely, CA, USA.

19 - PITAC, P. I. (1999). Information Technology Research: Investing in Our Future. Report to

the President. Technical report.

20 - POWELL, T., SCHNEIDER, F., (2001). Javascript: The Complete Reference. McGraw-Hill

Professional.

Page 19: UM MECANISMO DE DEPURAÇÃO PARA SISTEMAS DISTRIBUÍDOS · Departamento de Informática al 2009]. Ambos promovem extensões para a linguagem C++, mas D³S utiliza uma linguagem de

Departamento de Informática

21 - POWELL, T. (2008). Ajax: The Complete Reference (1 ed.). McGraw-Hill, Inc., New York,

NY, USA.

22 - REYNOLDS, P., KILLIAN, C.E.,WIENER, J.L.,MOGUL, J.C., SHAH, M.A., VAHDAT, A.

(2006). Pip: Detecting the Unexpected in Distributed Systems. In: Proceedings of the

ACM/USENIX Symposium on Networked Systems Design and Implementation (NSDI)

23 - ROSSUM, G. VAN (1991). Python Disponível em: http://python.org/ Acesso em:12 jun 2012.

24 - STONEBRAKER, M. (2010). SQL databases v. NoSQL databases. Commun. ACM 53, 4 (April

2010), 10-11. DOI=10.1145/1721654.1721659 http://doi.acm.org/10.1145/1721654.1721659

25 - THOMAS, D. A. (2002). The deplorable state of class libraries. Journal of Object Technology,

1(1):21–27.