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

Por que aprender Python pode impulsionar sua carreira em programação

Você que já automatiza suas rotinas com shell script precisa aprender Python. Dizem que se você quer trabalhar no Google o caminho mais fácil é aprender Python. Será que este

Desenvolvimento

Como criar um chat com PHP e Swoole: um guia passo a passo

Quando um desenvolvedor recebe a tarefa de implementar um chat dificilmente o PHP será a linguagem escolhida. Isso ocorre por alguns motivos, como por exemplo, dificilmente vermos o uso de

Desenvolvimento

Guia prático: aprenda a utilizar o Git e integrar com o Github

Conhecendo o Git Git – é uma das, senão a mais utilizada ferramente de SCM (Source Control Management) presentes no mercado de TI e um ponto muito importante, é disponibilizado