Entendendo as métricas do K6 - Parte 2
Tags: performance, testing, k6, go
Published: 2023-10-17 22:29:07

Na [primeira parte](https://dev.to/marlo2222/entendendo-as-metricas-do-k6-parte-1-4kig) desta serie de publicações, exploramos as métricas default geradas pelo K6. 

Nesse artigo, abordaremos as principais métricas geradas pelo K6 quando lidamos com os principais protocolos de rede do mercado.

## Protocolos de rede suportados pelo K6📑
Atualmente o K6 da suporte aos seguintes protocolos de rede:
- HTTP/1.1
- HTTP/2
- WebSockets
- gRPC

Ao termino de cada teste, serão geradas métricas correspondentes a cada protocolo utilizado, juntamente com as métricas default vistas na [parte 1](https://dev.to/marlo2222/entendendo-as-metricas-do-k6-parte-1-4kig). 

## Métricas HTTP📈
O k6 por padrão inicia as comunicações com servidores usando o protocolo HTTP/1.1. No entanto, caso o servidor sinalize ao k6 que é compatível com o protocolo HTTP/2, a ferramenta prontamente atualiza a conexão para utilizar o HTTP/2.

```
          /\      |‾‾| /‾‾/   /‾‾/
     /\  /  \     |  |/  /   /  /
    /  \/    \    |     (   /   ‾‾\
   /          \   |  |\  \ |  (‾)  |
  / __________ \  |__| \__\ \_____/ .io

  execution: local
     script: parte2_http.js
     output: -

  scenarios: (100.00%) 1 scenario, 1 max VUs, 10m30s max duration (incl. graceful stop):
           * default: 1 iterations for each of 1 VUs (maxDuration: 10m0s, gracefulStop: 30s)


     data_received..................: 17 kB 13 kB/s
     data_sent......................: 446 B 330 B/s
     http_req_blocked...............: avg=236.26ms min=236.26ms med=236.26ms max=236.26ms p(90)=236.26ms p(95)=236.26ms
     http_req_connecting............: avg=102.72ms min=102.72ms med=102.72ms max=102.72ms p(90)=102.72ms p(95)=102.72ms
     http_req_duration..............: avg=106.76ms min=106.76ms med=106.76ms max=106.76ms p(90)=106.76ms p(95)=106.76ms
       { expected_response:true }...: avg=106.76ms min=106.76ms med=106.76ms max=106.76ms p(90)=106.76ms p(95)=106.76ms
     http_req_failed................: 0.00% ✓ 0        ✗ 1
     http_req_receiving.............: avg=0s       min=0s       med=0s       max=0s       p(90)=0s       p(95)=0s
     http_req_sending...............: avg=0s       min=0s       med=0s       max=0s       p(90)=0s       p(95)=0s
     http_req_tls_handshaking.......: avg=118.57ms min=118.57ms med=118.57ms max=118.57ms p(90)=118.57ms p(95)=118.57ms
     http_req_waiting...............: avg=106.76ms min=106.76ms med=106.76ms max=106.76ms p(90)=106.76ms p(95)=106.76ms
     http_reqs......................: 1     0.738804/s
     iteration_duration.............: avg=1.35s    min=1.35s    med=1.35s    max=1.35s    p(90)=1.35s    p(95)=1.35s
     iterations.....................: 1     0.738804/s
     vus............................: 1     min=1      max=1
     vus_max........................: 1     min=1      max=1

```

As métricas HTTP serão geradas sempre que o modulo `k6/http` for utilizado nos seus testes, e somente quando uma requisição HTTP for realizada. Entre as métricas geradas que são introduzidas ao resultado de saída, temos: 

<table>
  <tr>
    <th>Métrica</th>
    <th>Tipo</th>
    <th>Descrição</th>
  </tr>
  <tr>
    <td>http_reqs</td>
    <td>Contador</td>
    <td>Quantos solicitações HTTP totais foram geradas pelo K6</td>
  </tr>
 <tr>
    <td>http_req_blocked</td>
    <td>Tendência</td>
    <td>Tempo gasto bloqueado a espera de um um slot de conexão TCP livre, antes de iniciar a solicitação.</td>
  </tr>
  <tr>
    <td>http_req_connecting</td>
    <td>Tendência</td>
    <td>Tempo gasto estabelecendo conexão TCP com o host remoto</td>
  </tr>
<tr>
    <td>http_req_tls_handshaking</td>
    <td>Tendência</td>
    <td>Tempo gasto na sessão TLS de handshaking com host remoto</td>
  </tr>
<tr>
    <td>http_req_sending</td>
    <td>Tendência</td>
    <td>Tempo gasto enviando dados para o host remoto</td>
  </tr>
<tr>
    <td>http_req_waiting</td>
    <td>Tendência</td>
    <td>Tempo gasto aguardando resposta do host remoto (também conhecido como “TTFB”)</td>
  </tr>
<tr>
    <td>http_req_receive</td>
    <td>Tendência</td>
    <td>Tempo gasto recebendo dados de resposta do host remoto</td>
  </tr>
<tr>
    <td>http_req_duration</td>
    <td>Tendência</td>
    <td>Tempo total para a solicitação HTTP</td>
  </tr>
<tr>
    <td>http_req_failed</td>
    <td>Taxas</td>
    <td>A taxa de solicitações com falha</td>
  </tr>
</table>

Entre todas as métricas uma das mais avaliadas é o  **_http_req_duration_**,  ele reflete o tempo total _(http_req_sending + http_req_waiting + http_req_receiving)_ que uma solicitação leva para ser totalmente processada, incluindo o tempo gasto em todas as fases de abertura e conexão, como:

- Tempo de conexão: O tempo que a solicitação leva para estabelecer uma conexão com o servidor.
- Tempo de envio: O tempo que a solicitação leva para ser enviada ao servidor.
- Tempo de processamento no servidor: O tempo que o servidor leva para processar a solicitação e gerar a resposta.
- Tempo de transmissão: O tempo que a resposta leva para ser transmitida de volta ao cliente.

Frequentemente utilizamos o **_http_req_duration_** para avaliar o desempenho de uma aplicação, pois permite medir o tempo total que os usuários ou sistemas esperam para receber uma resposta após fazer uma solicitação. No entanto, nossa avaliação deve ir muito além.

Se você perceber que uma quantidade significativa de tempo é consumida durante as fases de abertura de conexão, é fundamental avaliar métricas como **_http_req_blocked_**, **_http_req_connecting_** e **_http_req_tls_handshaking_**. Essas métricas nos possibilitam identificar problemas, como a roteirização de tráfego por balanceadores de carga em ambientes com múltiplos hosts, que podem impactar diretamente no tempo de estabelecimento da conexão segura.

Os gargalos de rede podem ser identificados por meio da análise de métricas como **_http_req_sending_** e **_http_req_receive_**. Essas métricas nos permitem avaliar possíveis problemas como a falta de servidores localizados geograficamente próximos aos clientes, ausência de redes de entrega de conteúdo (CDNs), bem como a necessidade de adotar estratégias eficientes de otimização de recursos do lado do cliente.

É de extrema importância monitorar a métrica **_http_req_waiting_**, uma vez que a lentidão na obtenção de respostas do servidor pode ser diretamente avaliada por meio dessa métrica. 

Ela nos permite investigar aspectos internos da aplicação, como o tempo gasto em integrações, solicitações a bancos de dados, a presença ou ausência de cache entre outros fatores. Além disso, é importante destacar que as métricas mencionadas anteriormente desempenham um papel significativo na influência do TTFB (Tempo até o Primeiro Byte).

## Métricas WebSocket📈
O K6 oferece suporte a testes baseados em WebSocket por meio do módulo `k6/experimental/websockets`. Esse protocolo possibilita o estabelecimento de canais de comunicação _**full-duplex**_ por meio de uma única conexão TCP, o que se mostra particularmente valioso em soluções de comunicação push do servidor.

```
          /\      |‾‾| /‾‾/   /‾‾/
     /\  /  \     |  |/  /   /  /
    /  \/    \    |     (   /   ‾‾\
   /          \   |  |\  \ |  (‾)  |
  / __________ \  |__| \__\ \_____/ .io

  execution: local
     script: parte2_socket.js
     output: -

  scenarios: (100.00%) 1 scenario, 1 max VUs, 10m30s max duration (incl. graceful stop):
           * default: 1 iterations for each of 1 VUs (maxDuration: 10m0s, gracefulStop: 30s)


     data_received.........: 1.8 kB 4.2 kB/s
     data_sent.............: 197 B  459 B/s
     iteration_duration....: avg=429.61ms min=429.61ms med=429.61ms max=429.61ms p(90)=429.61ms p(95)=429.61ms
     iterations............: 1      2.327665/s
     ws_connecting.........: avg=429.61ms min=429.61ms med=429.61ms max=429.61ms p(90)=429.61ms p(95)=429.61ms
     ws_session_duration...: avg=429.61ms min=429.61ms med=429.61ms max=429.61ms p(90)=429.61ms p(95)=429.61ms
     ws_sessions...........: 1      2.327665/s

```

Dentre as métricas que são automaticamente agregadas ao utilizar este protocolo, temos:
<table>
  <tr>
    <th>Métrica</th>
    <th>Tipo</th>
    <th>Descrição</th>
  </tr>
  <tr>
    <td>ws_connecting</td>
    <td>Tendência</td>
    <td>Duração total da solicitação de conexão WebSocket</td>
  </tr>
 <tr>
    <td>ws_session_duration</td>
    <td>Tendência</td>
    <td>Duração da sessão WebSocket. Tempo entre o início da conexão e o final da execução da VU</td>
  </tr>
  <tr>
    <td>ws_sessions</td>
    <td>Contador</td>
    <td>Número total de sessões WebSocket iniciadas</td>
  </tr>
<tr>
    <td>ws_ping</td>
    <td>Tendência</td>
    <td>Duração entre uma solicitação de ping e sua recepção de pong
</td>
  </tr>
<tr>
    <td>ws_msgs_sent</td>
    <td>Contador</td>
    <td>Número total de mensagens enviadas</td>
  </tr>
<tr>
    <td>ws_msgs_received</td>
    <td>Contador</td>
    <td>Número total de mensagens recebidas</td>
  </tr>
</table>

Entre as métricas do protocolo webSocket, devemos sempre estarmos atentos ao **_ws_connecting_**, **_ws_session_duration_** e **_ws_ping_**.

Analisando o **_ws_connecting_** poderemos avaliar o desempenho e a latência na fase de estabelecimento das conexões WebSocket. É importante manter esse tempo o mais baixo possível, especialmente em cenários de alta concorrência.

Com o **_ws_session_** poderemos avaliar o tempo que uma conexão WebSocket permanece ativa, o comportamento e a estabilidade das conexões, desde o momento em que é estabelecida até o momento em que é encerrada. Além disso, Pode ser usada para identificar sessões que duraram mais do que o esperado, o que pode indicar problemas de desempenho ou até mesmo vazamentos de conexão.

Por último, o **_ws_ping_** pode ser empregado para detectar possíveis gargalos na resposta do servidor (pong) após a solicitação do cliente (ping), além de avaliar a robustez e a capacidade de resposta de uma conexão.

## Métricas gRPC 📈
O K6 também oferece suporte a testes com o protocolo gRPC por meio do modulo integrado `k6/net/grpc` para solicitações  gRPC unárias, em um formato de comunicação binário que são descritas em arquivos `.proto`.

```
          /\      |‾‾| /‾‾/   /‾‾/
     /\  /  \     |  |/  /   /  /
    /  \/    \    |     (   /   ‾‾\
   /          \   |  |\  \ |  (‾)  |
  / __________ \  |__| \__\ \_____/ .io

  execution: local
     script: parte2_grpc.js
     output: -

  scenarios: (100.00%) 1 scenario, 1 max VUs, 10m30s max duration (incl. graceful stop):
           * default: 1 iterations for each of 1 VUs (maxDuration: 10m0s, gracefulStop: 30s)


     data_received........: 5.8 kB 3.2 kB/s
     data_sent............: 689 B  375 B/s
     grpc_req_duration....: avg=104.2ms min=104.2ms med=104.2ms max=104.2ms p(90)=104.2ms p(95)=104.2ms
     iteration_duration...: avg=1.83s   min=1.83s   med=1.83s   max=1.83s   p(90)=1.83s   p(95)=1.83s
     iterations...........: 1      0.544344/s
     vus..................: 1      min=1      max=1
     vus_max..............: 1      min=1      max=1

```

Em solicitações unárias uma única solicitação é enviada ao servidor que, por sua vez, responde com uma única resposta. Mas detalhes estão disponíveis no artigo do time do k6 [performance testing grpc services](https://k6.io/blog/performance-testing-grpc-services/).

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/731wuw8du4anaucum22q.png)

Entre as métricas que são incluídas por padrão ao usar o protocolo gRPC, destacam-se:

<table>
  <tr>
    <th>Métrica</th>
    <th>Tipo</th>
    <th>Descrição</th>
  </tr>
  <tr>
    <td>grpc_req_duration</td>
    <td>Tendência</td>
    <td>duração das solicitações gRPC</td>
  </tr>
 <tr>
    <td>grpc_streams</td>
    <td>Contador</td>
    <td>Número total de transmissões iniciadas</td>
  </tr>
  <tr>
    <td>grpc_streams_msgs_sent</td>
    <td>Contador</td>
    <td>Número total de mensagens enviadas
</td>
  </tr>
<tr>
    <td>grpc_streams_msgs_received</td>
    <td>Contador</td>
    <td>Número total de mensagens recebidas</td>
</tr>
</table>

A métrica chave do gRPC a ser prioritariamente avaliada é o **_grpc_req_duration_**. Essa métrica é essencial para avaliar o desempenho de operações _gRPC_, permitindo medir o tempo gasto em cada solicitação e identificar possíveis gargalos ou problemas de latência no sistema. É uma métrica crítica para otimizar o desempenho de serviços que usam o protocolo gRPC.

## Conclusão💖
Como podemos observar o K6 fornece uma serie de métricas para os principais protocolos de rede do mercado, permitindo analisar pontos críticos de desempenho nas aplicações.

No entanto é importante salientar que muitas outras métricas podem ser criadas utilizando métricas customizadas. Para mais detalhes consulte a documentação do K6 que trata sobre [create custom metrics](https://k6.io/docs/using-k6/metrics/create-custom-metrics/).

Gostou do conteúdo e quer saber mais sobre testes de performance com K6? Então não deixe de conferir meu curso na Udemy:

- [Teste de performance com K6](https://www.udemy.com/course/teste-de-performance-com-k6/?referralCode=95CCD8BC9F22A2A96BDA) ✨