Descubra como o Elastic APM pode melhorar a performance da sua aplicação

Descubra como o Elastic APM pode melhorar a performance da sua aplicação

Heeey!

E já que venho aqui sempre para falar de elasticsearch …

Estou aqui para explorar o Elastic APM  :]

Primeiramente, APM significa Monitoramento de performance de Aplicação (Application Performance Management), é utilizado para realizar monitoramento, rastreamento e análise tanto para o frontend quanto para o backend de uma aplicação.

É uma ferramenta é gratuita e aberta e tem o diferencial que é a capacidade de integrar a monitoração da sua aplicação com a infraestrutura que a cerca. Através do Kibana, você consegue fazer um rastreamento das transações, erros, logs, métricas e uptime.

Elastic Apm integração

Para utilizar o APM, é preciso instalar um agente, que nada mais é que uma biblioteca que será capaz de coletar dados de desempenho e erros em tempo de execução. Esses dados são armazenados em buffer por um curto período e enviados ao APM Server. Os agentes estão disponíveis para as seguintes linguagens:

Vamos para a prática!

Utilizaremos uma aplicação em Flask, bem simples (programar nã é muito meu forte haha) mas servirá para a gente ter um bom overview do que o Elastic APM pode oferecer :]


Para configurar o agent do APM na aplicação, fiz os seguintes passos:

Instalei a bibliteca via pip
pip install elastic-apm[flask]

Configurei o serviço dentro do arquivo app.py

app.config['ELASTIC_APM'] = {
  'SERVICE_NAME': '4coffeeApp',
  'SERVER_URL': 'http://apm-server:8200',
  'ENVIRONMENT': 'production',
}


apm = ElasticAPM(app)

Para começar, monter esse docker-compose:

version: '2.2'
services:
  apm-server:
    image: docker.elastic.co/apm/apm-server:7.17.6
    depends_on:
      elasticsearch:
        condition: service_healthy
      kibana:
        condition: service_healthy
    cap_add: ["CHOWN", "DAC_OVERRIDE", "SETGID", "SETUID"]
    cap_drop: ["ALL"]
    ports:
    - 8200:8200
    networks:
    - elastic
    command: >
       apm-server -e
         -E apm-server.rum.enabled=true
         -E setup.kibana.host=kibana:5601
         -E setup.template.settings.index.number_of_replicas=0
         -E apm-server.kibana.enabled=true
         -E apm-server.kibana.host=kibana:5601
         -E output.elasticsearch.hosts=["elasticsearch:9200"]
    healthcheck:
      interval: 10s
      retries: 12
      test: curl --write-out 'HTTP %{http_code}' --fail --silent --output /dev/null http://localhost:8200/

  elasticsearch:
    image: docker.elastic.co/elasticsearch/elasticsearch:7.17.6
    environment:
    - bootstrap.memory_lock=true
    - cluster.name=docker-cluster
    - cluster.routing.allocation.disk.threshold_enabled=false
    - discovery.type=single-node
    - ES_JAVA_OPTS=-XX:UseAVX=2 -Xms1g -Xmx1g
    ulimits:
      memlock:
        hard: -1
        soft: -1
    volumes:
    - esdata:/usr/share/elasticsearch/data
    ports:
    - 9200:9200
    networks:
    - elastic
    healthcheck:
      interval: 20s
      retries: 10
      test: curl -s http://localhost:9200/_cluster/health | grep -vq '"status":"red"'

  kibana:
    image: docker.elastic.co/kibana/kibana:7.17.6
    depends_on:
      elasticsearch:
        condition: service_healthy
    environment:
      ELASTICSEARCH_URL: http://elasticsearch:9200
      ELASTICSEARCH_HOSTS: http://elasticsearch:9200
    ports:
    - 5601:5601
    networks:
    - elastic
    healthcheck:
      interval: 10s
      retries: 20
      test: curl --write-out 'HTTP %{http_code}' --fail --silent --output /dev/null http://localhost:5601/api/status

  4coffee_app:
    build:
      context: ../
      dockerfile: deployment/Dockerfile
    command: gunicorn --bind  0.0.0.0:5001 wsgi:app --timeout 0
    depends_on:
      - apm-server
    expose:
      - 5001
    env_file:
      - .env
    networks:
    - elastic

  nginx:
    build: ./nginx
    depends_on:
      - 4coffee_app
    ports:
      - 8080:80
    depends_on:
      - 4coffee_app
    networks:
    - elastic


volumes:
  esdata:
    driver: local

networks:
  elastic:
    driver: bridge

Suba todos os serviços com

docker compose up -d

Assim que todos os serviços subirem, o kibana já estará disponível através na porta 5601 (o adaptador de rede do docker-compose está no modo brigde).

O APM fica na seção Observability do Kibana, ao acessá-lo, você já visualizará os services disponíveis:

APM Home

Ao clicar na aplicação, teremos 4 abas em destaque:

Overview
Te mostrará todas as informação e gráficos importantes.

Overview-1

Overview-2

Overview-3

Transactions
Te mostrará alguns gráficos e informações bem detalhas de todas as transações

Transactions

Transactions2

Transactions3

Transactions4

Dependencies
Te mostrará detalhes sobre todas as dependencias e o quanto elas estão impactando nas transações da sua aplicação. No nosso caso, não aparecerá pois o service map não é uma feature suportada através da licença BASIC.

Errors
Te mostrará todos as informações dos erros que ocorreram nas transações ou nas dependencias.

Errors-1

Errors-2

Errors-3

Metrics
Te mostrará métricas da aplicação em relação ao uso de CPU e Memória

Metrics

Na parte de transações, da para fazer algumas correlações e comparação com o dia anterior, infelizmente, as análises de correlações apenas está disponível na licença platinum, porquê é uma feature do Machine Learning.


*Aproveitando que minha infra tem um Nginx…

Habilitei métricas e logs através do módulo do nginx (tanto para metrcibeat quanto para filebeat). E obtive as seguintes visualizações:

  • Metricbeat

Metricbeat-nginx

Metricbeat-nginx-2

  • Filebeat

Filebeat

Filebeat-2



É importante destacar que simulei as requests de usuários simultaneamente através da ferramenta Locust. Segue exemplo:

from locust import HttpUser, task, between
from random import randint
import random, string


def randomword(length):
    letters = string.ascii_lowercase
    return ''.join(random.choice(letters) for i in range(length))


class WebsiteUser(HttpUser):
    wait_time = between(1, 3)
    @task()
    def index(self):
        self.client.get("/")

    @task()
    def index(self):
        self.client.get("/items/all")

    @task()
    def create(self):
        self.client.post("/insert_data",json={
            "id": randint(0,100),
            "bebida": f"cafe{randomword(10)}",
            "preço": randint(0,100),
            "açucar": "false"
          }
        )


É isso pessoal! A aplicação e os arquivos estarão disponíveis no meu github, fiquem a vontade para testar e modificar <3

Até mais o/

Líder em Treinamento e serviços de Consultoria, Suporte e Implantação para o mundo open source. Conheça nossas soluções:

CURSOSCONSULTORIA

Anterior Descubra as melhores soluções de dashboards para Kubernetes
Próxima Dia do Profissional de Informática: Conheça as datas comemorativas da área

About author

Thaynara Mendes
Thaynara Mendes 4 posts

Formada em Ciência da Computação. Apaixonada por Linux e café. Atuou na área de desenvolvimento back-end com a linguagem Python e atua como Devops na 4linux, possui a cerficação LPIC-1 e ministra aula do curso de Infraestrutura Ágil com Práticas DevOps e Especialista em Elastic Stack.

View all posts by this author →

Você pode gostar também

Desenvolvimento

Como criar uma API funcional com Laravel: Rotas, Controller e HTTP Status Code

Neste segundo post, iremos ver a nossa API Laravel funcional e mostrar na tela os nossos resultados. Iremos ver como o Laravel torna simples a criação de Rotas e Controller,

Cloud

Descubra como o Skaffold pode otimizar seu trabalho com Kubernetes

Olá pessoal! A ideia para este post surgiu quando me deparei com o problema, que todos que trabalham ou vão trabalhar com Kubernetes enfrentam: a necessidade de a cada simples

DevOps

Automatização de ambientes com Rundeck

Por que automatizar seu ambiente? Nos últimos anos, a automação tem crescido como um elemento imperativo em todos os negócios. Independente da área, temos observado um notável aumento no uso