A última coisa que uma empresa deseja é ser conhecida como um serviço não confiável e com baixo desempenho, especialmente se houver soluções semelhantes a alguns cliques de distância. Portanto, estar ciente do desempenho de um aplicativo WebRTC ou qualquer outra solução de software é essencial para evitar problemas no futuro. Uma solução pode ser desenvolvida por pessoas experientes e testada antes de ser lançada, mas mesmo assim isso não significa que nunca ocorrerão degradações de desempenho. Perceber os problemas com antecedência e agir de acordo pode ajudar muito a fazer com que os usuários tenham uma experiência melhor.
Imagine que seu aplicativo de chamada de vídeo apresenta problemas quando ocorre perda de pacotes . A perda de pacotes pode causar áudio instável, vídeo congelado ou falta de quadros de vídeo, tornando difícil para os usuários entender o que está sendo dito ou ver o que está acontecendo na chamada. A alta perda de pacotes também pode dificultar o estabelecimento e a manutenção de uma conexão pelo aplicativo, levando à queda de chamadas ou bate-papos por vídeo. Se você e sua equipe não tiveram perda de pacotes enquanto trabalhavam no desenvolvimento do aplicativo, há uma maneira de descobrir que há um problema - um cliente desapontado pode informá-lo sobre sua experiência desagradável. Obviamente, seria muito melhor descobrir o problema e corrigi-lo antes que os usuários o experimentassem.
É por isso que o monitoramento é uma prática tão benéfica – observar regularmente o desempenho e o comportamento do produto ao longo do tempo permite que você reaja rapidamente a quaisquer problemas que surjam e mantenha um serviço confiável e de alto desempenho. Isso não apenas melhora a experiência do usuário, levando a uma maior satisfação e fidelidade do cliente, mas também dá à sua empresa uma vantagem competitiva no mercado.
Benefícios do monitoramento regular de aplicativos:
O Loadero é uma ferramenta de teste de carga e desempenho capaz de simular o comportamento real do usuário e a interação com sites usando tecnologias de automação da Web, como “Javascript + Nightwatch”, “Java + TestUI” ou “Python + Py-TestUI”. Junto com isso, ele fornece todas as estatísticas necessárias do WebRTC e da máquina, como FPS, taxa de bits, jitter, tempo de ida e volta e outras, que foram coletadas durante a execução do teste e é capaz de afirmá-las.
Como o monitoramento requer observação constante, por exemplo, execuções de teste constantes em nosso caso, também precisaríamos acionar execuções de teste periodicamente. Para esse propósito, um pipeline de CI/CD é uma ótima escolha, pois é flexível e não é complicado de configurar para nossa tarefa. Além de executar os testes periodicamente, o pipeline também pode ser usado para automatizar os testes após cada implantação para garantir que o desempenho esteja bom.
Para começar a monitorar sua solução WebRTC com Loadero, é necessária uma configuração composta por 3 partes:
Vamos começar configurando o teste Loadero para nosso exemplo de configuração de monitoramento. Se você já tem um teste no Loadero, que pode ser iniciado para verificar algumas das métricas de desempenho, pode pular esta parte e pular para a parte sobre o lançamento de testes por meio do pipeline. Se for a primeira vez que você trabalha em um teste no Loadero, um guia passo a passo completo sobre como criar um teste no Loadero pode ser encontrado nesta postagem do blog . Se você já possui um teste de desempenho WebRTC em outro serviço, veja aqui como migrar seu teste para o Loadero. No nosso caso, teremos um teste “Javascript + Nightwatch”. O cenário será uma chamada individual de um minuto em Jitsi .
No teste, dois participantes entrarão em uma chamada e permanecerão nela por um minuto, tirando algumas capturas de tela no meio do caminho para verificação adicional da conexão.
Os participantes se conectarão de US Oregon, usarão a versão mais recente do Google Chrome (109v no momento da redação deste blog) e usarão vídeo + áudio padrão para simular o sinal de saída.
Também usaremos as asserções pós-execução do Loadero. Eles permitem que você especifique os critérios de “aprovação” para WebRTC e/ou métricas de máquina em seu teste, como “se FPS médio ≥ 10, então passe”. Após a conclusão da execução, os resultados de assert são calculados automaticamente para cada participante para verificar se os valores fornecidos atenderam aos critérios de aprovação. Se a assertiva falhou para um participante, o status desse participante no relatório de resultados também será "Reprovado".
Com as declarações, avaliaremos a taxa de bits e os pacotes de entrada e saída para áudio e vídeo, bem como FPS.
A configuração do nosso teste seria algo assim:
Neste exemplo temos um script de teste Loadero escrito em Javascript + Nightwatch, mas o mesmo pode ser feito com Java + TestUI ou Python + Py-TestUI.
client => { client // Open the page .url(`https://meet.jit.si/LoaderoTests`) // Wait until the username field is visible // And enter the username .waitForElementVisible('[placeholder]', 30 * 1000) .sendKeys('[placeholder]', 'User') // Wait until the "Join" button is visible // And join the call by pressing the button .waitForElementVisible('[aria-label="Join meeting"]', 10 * 1000) .click('[aria-label="Join meeting"]') // Another thing you can do is to take screenshots during the test // Which could help you to identify the cause of a failure // And give visual feeback about the test run .takeScreenshot('pre_call_screenshot.png') // Stay in the call for half a minute .pause(30 * 1000) // Take a mid-call screenshot .takeScreenshot('mid_call_screenshot.png') // Stay in the call for another half a minute .pause(30 * 1000) // Take a post-call screenshot .takeScreenshot('post_call_screenshot.png'); }
Cada aplicativo WebRTC é diferente e terá um desempenho ligeiramente diferente. Aqui pretendemos definir os limites onde queremos ser imediatamente notificados se as expectativas de desempenho não forem atendidas, mesmo que isso aconteça durante a noite. Para fazer isso, usaremos um conjunto de asserções pós-execução do Loadero para métricas WebRTC, o que fará com que toda a execução do teste falhe se os valores das métricas de desempenho WebRTC não forem tão bons quanto gostaríamos. Portanto, os valores-alvo não devem ser definidos em margens estreitas, mas devemos permitir que os testes sejam ocasionalmente um pouco piores do que gostaríamos, mas ainda dentro de um desempenho razoável. Os valores que definimos aqui são exemplos e você pode querer ajustá-los com base nas especificidades do aplicativo (por exemplo, se você priorizar uma taxa de quadros alta em relação à largura de banda da rede, talvez queira aumentar a taxa de quadros mínima que deseja ver e diminuir os limites da taxa de bits). Como ponto de partida, você pode usar a lista de asserts abaixo:
Aqui está a lista de asserções e seus valores que definimos para este teste de exemplo:
webrtc/video/fps/out/25th >= 10
webrtc/video/fps/in/25th >= 10
webrtc/video/fps/out/stddev < 2
webrtc/video/fps/in/stddev < 2
webrtc/audio/packets/out/avg > 40/sec
webrtc/video/packets/out/avg > 100/sec
webrtc/audio/packets/in/avg > 40/sec
webrtc/video/packets/in/avg > 100/sec
webrtc/audio/bitrate/out/95th <= 25 kbit/sec
webrtc/video/bitrate/out/95th <= 1000 kbit/sec
webrtc/audio/bitrate/in/95th <= 25 kbit/sec
webrtc/video/bitrate/in/95th <= 1000 kbit/sec
Finalmente, temos que configurar os participantes do teste. Teremos 1 grupo de participantes que terá 2 participantes com a mesma configuração que entrarão na chamada. A configuração dos participantes é a seguinte:
Dica: se você quiser ter muitos participantes exatamente com a mesma configuração, então no menu de configuração aumente o valor
Count
. Para economizar seu tempo, sugerimos criar participantes individualmente apenas no caso de eles precisarem ter configurações diferentes.
Para a configuração de teste seria isso. Mas como pretendemos que nosso teste seja executado regularmente, antes de prosseguirmos com a configuração do monitoramento, execute o teste e verifique se o script não está com falhas, verificando os logs e capturas de tela do Selenium que os participantes tiraram durante a execução do teste. Se for a primeira vez que você inicia um teste no Loadero, ou simplesmente não tem certeza se ele foi configurado corretamente, use esta postagem do blog para verificar se o seu teste está pronto para ser iniciado .
Conforme mencionado anteriormente, os participantes ainda podem falhar se as afirmações da métrica WebRTC falharem e a taxa de sucesso pode não ser de 100%. Isso aconteceu para o nosso teste também.
Isso não significa necessariamente que o teste está com defeito, apenas que o aplicativo não atende aos critérios de asserção que você definiu. Mas se o seu teste falhou devido a outro motivo, não ao conjunto de asserções, esta postagem do blog explica algumas maneiras de depurar seu teste.
As declarações que definimos são apenas uma linha de base geral não adaptada ao aplicativo que testamos. Você pode usar a lista e começar com esses valores, mas o aplicativo testado pode ser diferente e os resultados da métrica também podem ser muito diferentes.
Dica: Uma boa maneira de definir suas próprias afirmações seria fazer 5 execuções de teste, observar as métricas dos participantes e avaliar metas razoáveis.
Definir essas asserções e analisar os resultados para descobrir por que as asserções falharam é uma tarefa complexa em si, portanto, não entraremos em muitos detalhes sobre isso nesta postagem do blog. Além disso, o fato de nosso teste de exemplo ter falhado devido a uma falha de asserção simula exatamente o caso que precisamos, quando um teste falhou e uma notificação sobre a falha é enviada, então vamos deixar como está. Se os logs do Selenium mostrarem que você não encontrou nenhum erro e as capturas de tela confirmarem que todas as ações necessárias foram executadas, o teste ainda estará pronto.
Nossa equipe já preparou algumas postagens de blog sobre como integrar testes em seu pipeline de desenvolvimento: usando JS e o cliente Python do Loadero . Portanto, aqui vamos contar com eles. Para nossa configuração usaremos o que é sugerido no post do blog que usa Python, GitHub e sua implementação de CI/CD – Workflows juntamente com o cliente Loadero Python.
Observação: algumas informações podem ser omitidas. Para obter instruções detalhadas, consulte a postagem original do blog Loadero Python .
Para o nosso fluxo de trabalho, precisaremos de:
Crie um novo repositório no GitHub ou use um existente.
Em seu repositório no diretório .github/workflows
crie um arquivo notify-on-fail.yml
. Este é o arquivo que conterá as instruções de como configurar o ambiente e iniciar o teste Loadero.
Vamos começar a definir o fluxo de trabalho especificando os gatilhos no notify-on-fail.yml
.
on: schedule: - cron: '0 9-18 * * *' workflow_dispatch:
schedule
permite acionar um fluxo de trabalho em um horário agendado. Portanto, é o local onde você define a frequência das execuções de teste. Em nosso exemplo, definimos o cronograma para executar o teste a cada hora, das 9h às 18h, pois é o horário em que a equipe tem maior probabilidade de reagir à falha. No caso de precisar executar testes durante todo o ciclo dia-noite, você pode preferir executá-los a cada 4 horas ou mais. Assim você monitora o app mesmo quando ninguém está acordado. Preste atenção, esse schedule
usa uma sintaxe específica mais sobre a qual você pode aprender aqui .
Dica : Ao definir a frequência dos testes, considere que o período entre as execuções do teste deve ser maior que a duração do teste, pois seus testes podem interferir uns nos outros.
O segundo gatilho – workflow_dispatch
– permite acionar o pipeline manualmente por meio do aplicativo da web GitHub, se necessário.
Em nossa seção jobs
do script, especificamos o ambiente e todas as dependências que usaremos. Para o nosso propósito, a configuração da postagem do blog Loadero Python se encaixa perfeitamente, portanto, não hesite em copiá-la e colá-la.
jobs: notify-on-fail: runs-on: ubuntu-latest steps: - uses: actions/checkout@v3 - uses: actions/setup-python@v4 with: python-version: "3.10" - run: pip install loadero-python - run: python run.py env: LOADERO_ACCESS_TOKEN: ${{ secrets.ACCESS_TOKEN }} LOADERO_PROJECT_ID: ${{ secrets.PROJECT_ID }} LOADERO_TEST_ID: ${{ secrets.TEST_ID }}
Importante: preste atenção, que na linha
- run: python run.py
, depois do python temos o caminho para o seu arquivorun.py
relativo à raiz do repositório. No meu caso, a estrutura do arquivo ficará assim:
Outra coisa a prestar atenção são as credenciais. Em primeiro lugar, você pode encontrar o teste e o ID do projeto no Loadero, mas também precisará de um token de acesso à API do projeto – atualmente, os tokens de acesso do projeto são adquiridos solicitando-os à nossa equipe de suporte. Em segundo lugar, as credenciais são usadas como segredos do GitHub Actions. Isso mantém seu token de acesso Loadero privado. Os segredos podem ser configurados nas configurações do repositório -> Segurança -> Segredos e variáveis -> Ações -> Novo segredo do repositório.
Para obter instruções passo a passo detalhadas sobre os segredos, consulte a postagem do blog mencionada anteriormente.
Portanto, a configuração do fluxo de trabalho por enquanto deve ser algo como isto:
name: Notify about failing tests in Loadero on: schedule: - cron: '0 9-18 * * *' workflow_dispatch: jobs: notify-on-fail: runs-on: ubuntu-latest steps: - uses: actions/checkout@v3 - uses: actions/setup-python@v4 with: python-version: "3.10" - run: pip install loadero-python - run: python run.py env: LOADERO_ACCESS_TOKEN: ${{ secrets.ACCESS_TOKEN }} LOADERO_PROJECT_ID: ${{ secrets.PROJECT_ID }} LOADERO_TEST_ID: ${{ secrets.TEST_ID }}
Agora vamos adicionar à nossa configuração o script Python para interagir com o Loadero. Mais uma vez, o script do blog Loadero Python é um ótimo ponto de partida, então vamos usá-lo e modificá-lo mais tarde para nossas necessidades.
import os from loadero_python.api_client import APIClient from loadero_python.resources.test import Test project_id = os.environ.get("LOADERO_PROJECT_ID", None) access_token = os.environ.get("LOADERO_ACCESS_TOKEN", None) test_id = os.environ.get("LOADERO_TEST_ID", None) if project_id is None or access_token is None or test_id is None: raise Exception( "Please set the " "LOADERO_PROJECT_ID and LOADERO_ACCESS_TOKEN AND LOADERO_TEST_ID " "environment variables." ) APIClient( project_id=project_id, access_token=access_token, ) run = Test(test_id=test_id).launch().poll() print(run) for result in run.results()[0]: print(result) if run.params.success_rate != 1: raise Exception("Test failed")
Agora é hora de modificar nosso script Python para implementar nossas notificações. Neste exemplo, o alerta será enviado para um canal do Discord. Embora a forma como você implementa as notificações seja totalmente opcional, pois depende de suas preferências pessoais.
Vamos atualizar nosso arquivo Python importando a biblioteca request, as classes ResultStatus
e AssertStatus
.
import requests import os from loadero_python.api_client import APIClient from loadero_python.resources.test import Test from loadero_python.resources.classificator import ResultStatus, AssertStatus
Além de atualizar nosso arquivo YAML para instalar a biblioteca request.
- run: pip install loadero-python - run: pip install requests - run: python run.py
Caso o pipeline esteja mal configurado e o valor de qualquer uma das credenciais seja None, devemos notificar nosso canal Discord sobre isso enviando uma solicitação POST com a mensagem de erro.
missing_credentials_message = ( "Please set the " "LOADERO_PROJECT_ID and LOADERO_ACCESS_TOKEN AND LOADERO_TEST_ID " "environment variables." ) def send_notification(message): requests.post( "https://discordapp.com/api/webhooks/{id}", data={"content": message}, ) if project_id is None or access_token is None or test_id is None: send_notification(missing_credentials_message) raise Exception(missing_credentials_message)
Se o teste falhar, gostaríamos de saber o motivo. Aqui adicionamos a verificação do participante. Se um participante falhar, enviamos a mensagem de erro com a seguinte estrutura:
Além disso, devemos nos livrar da exceção que o script inicial tinha, pois é excessivo aqui
run_failure_message = "" for result in run.results()[0]: result.params.run_id = run.params.run_id result.read() if ( result.params.selenium_result.value != ResultStatus.RS_PASS or result.params.status.value != ResultStatus.RS_PASS ): run_failure_message += ( f"{result.params.participant_details.participant_name}:\n" f"-Selenium result: {result.params.selenium_result.value}\n" f"-Participant status: {result.params.status.value}\n" ) if result.params.asserts: run_failure_message += "-Failing asserts:\n" for assertion in result.params.asserts: if assertion.status != AssertStatus.AS_PASS: run_failure_message += f"--{assertion.path.value}\n" run_failure_message += "\n" run_failure_message += f"Run status: {run.params.status.value}" if run.params.success_rate != 1: send_notification(run_failure_message)
E também vamos enviar uma mensagem para o teste bem-sucedido:
if run.params.success_rate != 1: send_notification(run_failure_message) else: send_notification(f"The {run.params.test_name} test has been finished successfully")
Como verificação final, devemos agrupar toda a chamada da API em try-except
no caso de a conexão com a API do Loadero estar com defeito. O script python final se parece com isso:
import os import requests from loadero_python.api_client import APIClient from loadero_python.resources.test import Test from loadero_python.resources.classificator import ResultStatus, AssertStatus project_id = os.environ.get("LOADERO_PROJECT_ID", None) access_token = os.environ.get("LOADERO_ACCESS_TOKEN", None) test_id = os.environ.get("LOADERO_TEST_ID", None) missing_credentials_message = ( "Please set the " "LOADERO_PROJECT_ID and LOADERO_ACCESS_TOKEN AND LOADERO_TEST_ID " "environment variables." ) def send_notification(message): requests.post( "https://discordapp.com/api/webhooks/{id}", data={"content": message}, ) if project_id is None or access_token is None or test_id is None: send_notification(missing_credentials_message) raise Exception(missing_credentials_message) try: APIClient( project_id=project_id, access_token=access_token, ) run = Test(test_id=test_id).launch().poll() print(run) run_failure_message = "" for result in run.results()[0]: result.params.run_id = run.params.run_id result.read() if ( result.params.selenium_result.value != ResultStatus.RS_PASS or result.params.status.value != ResultStatus.RS_PASS ): run_failure_message += ( f"{result.params.participant_details.participant_name}:\n" f"-Selenium result: {result.params.selenium_result.value}\n" f"-Participant status: {result.params.status.value}\n" ) if result.params.asserts: run_failure_message += "-Failing asserts:\n" for assertion in result.params.asserts: if assertion.status != AssertStatus.AS_PASS: run_failure_message += f"--{assertion.path.value}\n" run_failure_message += "\n" run_failure_message += f"Run status: {run.params.status.value}" if run.params.success_rate != 1: send_notification(run_failure_message) else: send_notification( f"The {run.params.test_name} test has been finished successfully" ) except Exception as err: send_notification(f"Error while running Loadero test: {err}")
Agora, nosso teste é executado automaticamente a cada hora, das 9h às 18h, e avalia se o aplicativo funciona conforme o esperado.
Após o término da execução do teste, em caso de falha no teste, você é notificado sobre a falha.
No nosso caso, o teste Jitsi falhou devido a FPS e pacotes que não atendem aos nossos critérios, o que pode ser visto na guia Asserts do resultado do teste. Os resultados do assert também são acessíveis para cada participante individualmente, assim você pode verificar se o problema ocorreu para todos os participantes ou apenas para uma parte deles.
Os valores fornecidos acima para os asserts podem servir como uma referência inicial, e parece que no nosso caso eles não se alinham com o desempenho alvo do Jitsi. Portanto, não hesite em explorar o desempenho do seu aplicativo e quais afirmações se encaixam melhor no seu aplicativo, para garantir que o processo de monitoramento seja ideal.
Observação: apenas observando as declarações de nosso teste, podemos notar que há seções inteiras que geram zeros durante a execução do teste, o que acaba afetando os resultados do teste.
Dica: Se seu teste falhou, você pode navegar até a aba de estatísticas WebRTC, onde você pode encontrar vários gráficos com dados e obter mais informações sobre a métrica que causou a falha.
Nesta postagem de blog, fornecemos um exemplo de como você pode monitorar seu aplicativo WebRTC com a ajuda do Loadero e dos fluxos de trabalho do GitHub. Com o uso do monitoramento, você está mais bem equipado para lidar com quaisquer problemas que possam surgir em sua aplicação. Também pode ser sensato criar outros cenários com condições diferentes para uma visão mais holística do desempenho do aplicativo. Definir esse monitoramento pode ser uma tarefa bastante complexa. Você gostaria que a equipe do Loadero criasse uma configuração de monitoramento semelhante para você? Sinta-se à vontade para nos contatar em [email protected] e vamos discutir como podemos ajudá-lo a monitorar regularmente e automaticamente sua solução WebRTC.
Publicado também aqui .