ElasticAPM e Apdex
Apdex (Application Performance Index) é uma medida de qualidade de serviço bem aceita na comunidade de tecnologia que tenta mensurar a satisfação do usuário com o tempo de resposta dos requests da aplicação. ElasticSearch você pode me ajudar?
Primeiro precisamos entender como chegamos neste número. O número é calculado através desta formula, resultando em uma razão entre 0 e 1, sendo valores mais altos a indicação de uma satisfação maior.
A idéia é contar as requisições com o tempo de respostas satisfatório como 1, as requisições com tempo de resposta tolerável como 0.5 e as requisições com tempo de resposta superior ao tolerável como 0 e por fim calcular a média. O limiar de uma requisição com o tempo satisfatório chamamos de t e o valor tolerável é definido por 4*t.
Supondo que tivemos no nosso site 1000 requisições e consideramos o valor satisfatório como 1 segundo, e o valor tolerável será 4 segundos. Vejamos um exemplo de cálculo:
+----------------------+-------------------------+
| 600 requests | abaixo de 1 segundo |
| 300 requests | entre 1 e 4 segundos |
| 100 requests | acima de 4 segundos |
-------------------------------------------------- 600*1 + 300*0.5 + 100*0
apdex = -------------------------- = 0.75
1000
Nessa simulação, o score apdex da aplicação , no período, foi 0.75 .
Bem, vamos agora realizar esse cálculo no ambiente do elasticapm. Primeiramente vamos subir o ambiente e uma aplicação de testes. O setup da stack do elastic será feito através de um docker-compose no projeto do github. Criamos a stack usando network_mode: host a fim de facilitar a interconexão dos serviços e a configuração do apm-server.yml, onde configuramos o secret token, que será utilizado na instrumentação da aplicação:
apm-server:
host: 0.0.0.0:8200
secret_token: changemeoutput:
elasticsearch:
hosts: ["localhost:9200"]
username:
password:
A aplicação foi desenvolvida em python, usando o framework flask, simplesmente retornando uma mensagem de ok após um timeout randomico. A imagem da aplicação foi construída usando:
docker build -t python-tst .docker run -it -m 400m --network=host python-tst
A imagem já está com as variáveis de conexão configuradas, mas as variáveis de ambiente mais importantes que precisamos configurar são as seguintes:
ELASTIC_APM_SERVICE_NAME=tst # nome do servico no apm
ELASTIC_APM_SECRET_TOKEN=changeme # secret token de ingestão
ELASTIC_APM_SERVER_URL=http://localhost:8200 # endereço do apmserver
O ApmServer possui muitas funcionalidades semelhante aos beats da elasticstack e uma funcionalidade bacana que nos atende é criar um ingest pipeline conforme a seguir. O nosso algoritmo consiste em criar um label chamado apdexscore, contendo o valor 1, 0.5 ou 0 conforme a duração em microsegundos da transaction. Definimos o fator t no script, como 800 milisegundos.
PUT /_ingest/pipeline/apmdex
{
"description": "ApDex",
"processors": [
{
"script": {
"lang": "painless",
"ignore_failure": true,
"source": """
double apdex_t = 800.0 * 1000;
if (ctx.labels==null) {
ctx.labels = [:];
}
if (ctx.transaction.duration.us <= apdex_t) {
ctx.labels.apdexscore=1.0;
}
else if (ctx.transaction.duration.us <= (apdex_t * 4)) {
ctx.labels.apdexscore=0.5;
}
else {
ctx.labels.apdexscore=0.0;
}
"""
}
}
]
}
Na verdade, a melhor opção é criar esse ingest no definition.json do apmserver. Neste arquivo definimos todos os pipelines criados no elasticsearch no momento da inicialização do apmserver. O pipeline principal disponível neste arquivo é o pipeline apm que na verdade é a composição de todos os pipelines que serão disparados no apmserver, onde anexamos o pipeline apmdex. Este arquivo deve ser mapeado no nosso docker-compose, a fim de carregar os definition no startup.
Agora vamos gerar um pouco de carga na aplicação. Para isso fiz uma chamada ao utilitário apache benchmark:
ab -c 30 -n 1000 http://localhost:5000/
Agora ficou fácil. Podemos fazer uma agregação de média nessa métrica num dashboard. O modo que achei mais pratico foi usar o componente gauge :
E o resultado final ficou assim:
Com certeza, num ambiente de microserviços vamos querer um gauge para cada microserviço (talvez um split group com buckets por serviço), mas isto vira detalhes de configuração do dashboard, que foge ao escopo deste artigo.
O elasticapm realmente se mostra como uma ferramenta muito versátil, mesmo funcionalidades não disponíveis em sua instalação padrão podemos customizar usando os recursos do ELK para atender as necessidades
Referências:
Github de apoio: