Monitoramento de desempenho da Web sem servidor usando Cloud Functions


Neste tutorial, descrevemos como criar um app de monitoramento de desempenho da Web usando tecnologias sem servidor do Google Cloud.

O desempenho é fundamental para o sucesso de qualquer app da Web. Caso seu site apresente baixo desempenho, talvez você tenha menos inscrições e menos retenção de usuários, o que provavelmente afetará suas metas de negócios. O desempenho é um critério importante para o sucesso ao projetar, criar e testar seu app da Web.

No entanto, o desempenho da página também pode mudar com o tempo, à medida que seu app evolui. Os desenvolvedores podem adicionar ou atualizar imagens e scripts, ou a própria infraestrutura subjacente de exibição de app pode mudar. Portanto, é importante monitorar regularmente o desempenho da página. O comum é armazenar as métricas de desempenho para ativar a análise histórica. Também é uma prática comum gerar alertas se o desempenho da página ficar abaixo de alguns limites definidos.

Objetivos

  • Criar uma Função do Cloud que use a versão headless do Chrome para coletar métricas de desempenho da página da Web.
  • Armazenar as métricas no Cloud Storage.
  • Criar outra Função do Cloud, acionada pelo evento de criação do Cloud Storage, para analisar as métricas da página.
  • Armazenar os resultados da análise no Firestore.
  • Criar outra Função do Cloud, acionada pelo evento de criação do Firestore, para publicar um alerta no Pub/Sub se o desempenho da página for fraco.
  • Criar um job do Cloud Scheduler para acionar periodicamente a primeira Função do Cloud.
  • Verificar os resultados para cenários de sucesso e de falha.

Custos

Neste tutorial, há componentes faturáveis do Google Cloud, inclusive estes:

  • Cloud Functions
  • Cloud Scheduler
  • Cloud Storage
  • Firestore
  • Pub/Sub
  • Container Registry
  • Cloud Build

Use a calculadora de preços para gerar uma estimativa de custo com base no uso previsto.

Antes de começar

  1. Faça login na sua conta do Google Cloud. Se você começou a usar o Google Cloud agora, crie uma conta para avaliar o desempenho de nossos produtos em situações reais. Clientes novos também recebem US$ 300 em créditos para executar, testar e implantar cargas de trabalho.
  2. No console do Google Cloud, na página do seletor de projetos, selecione ou crie um projeto do Google Cloud.

    Acessar o seletor de projetos

  3. Verifique se a cobrança está ativada para o seu projeto do Google Cloud.

  4. Ative as APIs Cloud Functions, Cloud Scheduler, Pub/Sub, and Cloud Build.

    Ative as APIs

  5. No console do Google Cloud, na página do seletor de projetos, selecione ou crie um projeto do Google Cloud.

    Acessar o seletor de projetos

  6. Verifique se a cobrança está ativada para o seu projeto do Google Cloud.

  7. Ative as APIs Cloud Functions, Cloud Scheduler, Pub/Sub, and Cloud Build.

    Ative as APIs

Arquitetura

As operações de monitoramento de desempenho da Web costumam ser sem estado e de curta duração. Elas também costumam ser orientadas por eventos, ocorrendo em uma programação ou acionadas como parte de algum outro processo, como um pipeline de teste automatizado. Com essas características, as arquiteturas sem servidor são uma opção atraente para implementar apps de análise da Web.

Neste tutorial, você usará várias partes da pilha sem servidor do Google Cloud, incluindo Cloud Functions, Firestore, Cloud Scheduler e Pub/Sub. Você não precisa gerenciar a infraestrutura de nenhum desses serviços e só paga pelo que usa. O núcleo do app é implementado usando o Cloud Functions, que fornece um ambiente de execução sem servidor orientado a eventos e escalonável. Com o Cloud Functions, é possível criar e conectar apps usando partes de lógica independentes e levemente acopladas.

No diagrama a seguir, veja a arquitetura da solução sem servidor que você criou neste tutorial.

Arquitetura da solução de análise da Web sem servidor

Como preparar o ambiente

Antes de criar o ambiente sem servidor, consiga o código do GitHub, defina as variáveis e prepare os recursos que serão necessários posteriormente para análise e armazenamento.

Receber o código e definir variáveis de ambiente

  1. No Console do Google Cloud, abra o Cloud Shell.

    Abra o Cloud Shell

  2. Clone o repositório que contém o código do Cloud Functions usado neste tutorial:

    git clone https://github.com/GoogleCloudPlatform/solutions-serverless-web-monitoring.git
    
  3. Passe para o diretório de funções:

    cd solutions-serverless-web-monitoring/functions
    
  4. Defina o ID e o número do projeto atual como variáveis de shell:

    export PROJECT=$DEVSHELL_PROJECT_ID
    export PROJECT_NUM=$(gcloud projects list \
        --filter="$PROJECT" \
        --format="value(PROJECT_NUMBER)")
    
  5. Defina a região de implantação padrão do Cloud Functions. No exemplo a seguir, definimos a região como us-east1, mas é possível alterá-la para qualquer região em que o Cloud Functions esteja disponível.

    export REGION=us-east1
    gcloud config set functions/region $REGION
    

Criar buckets do Cloud Storage

Nesta seção, você cria um bucket do Cloud Storage para armazenar os dados de desempenho da página coletados. É possível escolher qualquer local ou classe de armazenamento, mas é uma boa prática criar buckets no mesmo local das Funções do Cloud que os usarão.

  1. No Cloud Shell, exporte uma variável de shell para os nomes dos buckets do Cloud Storage que armazenarão as métricas. Como os nomes dos buckets precisam ser exclusivos globalmente, o comando a seguir usa o número do projeto do Google Cloud como sufixo do nome do bucket.

    export METRICS_BUCKET=page-metrics-$PROJECT_NUM
    
  2. Use a ferramenta gsutil para criar os buckets:

    gsutil mb -l $REGION gs://$METRICS_BUCKET
    
  3. Atualize o arquivo env-vars.yaml com os nomes dos buckets. Esse arquivo contém variáveis de ambiente que você passará para o Cloud Functions mais tarde.

    sed -i "s/\[YOUR_METRICS_BUCKET\]/$METRICS_BUCKET/" env-vars.yaml
    

Criar uma coleção do Firestore

Em uma seção posterior, você analisará as métricas de desempenho da página. Nesta seção, você cria uma coleção do Firestore para armazenar os resultados de cada análise.

  1. No Console do Google Cloud, acesse a página Firestore.

    Acessar a página do Firestore

  2. Se você nunca criou um banco de dados do Firestore antes, execute as seguintes etapas:

    1. Clique em Selecionar modo nativo para ativar o Firestore.
    2. Selecione um local regional próximo à região em que o Cloud Functions será executado.
    3. Clique em Criar banco de dados.

    A configuração leva alguns instantes.

  3. Clique em Iniciar coleção e defina o código da coleção como page-metrics.

  4. Clique em Salvar.

Criar um tópico e uma assinatura do Pub/Sub

O comum é notificar os sistemas e as partes interessadas se a análise indicar que o desempenho de uma página está fraco. Nesta seção, você cria tópicos do Pub/Sub contendo mensagens que descrevem qualquer desempenho insatisfatório.

  1. No Cloud Shell, crie um tópico Pub/Sub chamado performance-alerts:

    gcloud pubsub topics create performance-alerts
    
  2. Crie uma assinatura para o tópico. Você usa a assinatura para verificar se as mensagens de alerta estão sendo publicadas no tópico.

    gcloud pubsub subscriptions create performance-alerts-sub \
        --topic performance-alerts
    

Como coletar métricas de desempenho da página

Muitos sites usam JavaScript para renderizar dinamicamente o conteúdo da página. Como isso, a análise de desempenho fica mais complicada, porque o cliente precisa emular um navegador para carregar totalmente a página da Web. O ambiente de execução do Node.js para Cloud Functions é compatível com a versão headless do Chrome, que oferece a funcionalidade de um navegador da Web completo em um ambiente sem servidor.

O Puppeteer (em inglês) é uma biblioteca do Node.js criada pela equipe do Chrome DevTools que fornece uma API de alto nível para controlar a versão headless do Chrome. Por padrão, o Puppeteer instala uma versão recente do navegador junto com a biblioteca. Portanto, é possível adicionar o Puppeteer como dependência da Função do Cloud para facilitar o uso da versão headless do Chrome na função.

Medir e analisar o desempenho da página da Web é um assunto vasto e complexo. Para simplificar, neste tutorial, você usa o Puppeteer para coletar algumas métricas de desempenho de página de nível superior. No entanto, também é possível usar o Puppeteer e o Chrome DevTools Protocol (CDP) (em inglês) para coletar informações mais detalhadas, como traces da linha do tempo. Também é possível representar melhor sua experiência do usuário final emulando o congestionamento de rede e realizando limitação de CPU. Para uma boa introdução à análise do desempenho da página da Web, consulte o site para desenvolvedores da Web do Google Chrome (em inglês).

Há muitos fatores que influenciam os tempos de carregamento de páginas da Web, incluindo as características de desempenho do cliente. É importante estabelecer valores de referência usando as configurações de CPU e RAM do Cloud Functions.

No snippet a seguir, do arquivo tracer/index.js, veja como usar o Puppeteer para carregar a página da Web:

// launch Puppeteer and start a Chrome DevTools Protocol (CDP) session
// with performance tracking enabled.
browser = await puppeteer.launch({
  headless: true,
  args: ['--no-sandbox']
});
const page = await browser.newPage();
const client = await page.target().createCDPSession();
await client.send('Performance.enable');

// browse to the page, capture and write the performance metrics
console.log('Fetching url: '+url.href);
await page.goto(url.href, {
  'waitUntil' : 'networkidle0'
});
const performanceMetrics = await client.send('Performance.getMetrics');
options = createUploadOptions('application/json', page.url());
await writeToGcs(metricsBucket, filename, JSON.stringify(performanceMetrics), options);
  • No Cloud Shell, implante a Função do Cloud trace:

    gcloud functions deploy trace \
        --trigger-http \
        --runtime nodejs10 \
        --memory 1GB \
        --source tracer \
        --env-vars-file env-vars.yaml \
        --quiet
    

    A implantação da Função do Cloud pode levar vários minutos.

    Os parâmetros de implantação especificam que a função tenha um gatilho HTTP, use o ambiente de execução do Node.js e tenha 1 GB de memória. Essa quantidade de memória é necessária para executar a versão headless do Chrome. As variáveis de ambiente são fornecidas à função usando o arquivo env-vars.yaml.

Por padrão, o Cloud Functions acionado por HTTP permite invocações não autenticadas. Portanto, você precisa proteger a função do trace.

  • Remova o papel de IAM cloudfunctions.invoker de allUsers:

    gcloud beta functions remove-iam-policy-binding trace \
        --member allUsers \
        --role roles/cloudfunctions.invoker
    

Como analisar as métricas

Uma meta típica dos exercícios de monitoramento de desempenho da Web é rastrear o desempenho em relação a alguns comparativos de mercado definidos. Se uma determinada métrica exceder um limite esperado, ela poderá indicar que há problema com uma versão recente do software ou com a infraestrutura subjacente.

Nesta seção, você cria uma Função do Cloud em Python para analisar as métricas da página e manter os resultados em uma coleção do Firestore. Com a função, você avalia a métrica FirstMeaningfulPaint em relação a um limite esperado e marca o resultado da análise como problemático se o limite for excedido. FirstMeaningfulPaint é uma métrica voltada ao usuário que descreve, em termos gerais, quando uma página fica útil para o usuário. Você usa um gatilho do Cloud Storage para executar a função de análise sempre que um novo arquivo é gravado no bucket que contém as métricas.

No snippet a seguir, do arquivo analyzer/main.py, veja a lógica da função:

def analyze(data, context):
  """Function entry point, triggered by creation of an object in a GCS bucket.

  The function reads the content of the triggering file, analyses its contents,
  and persists the results of the analysis to a new Firestore document.

  Args:
    data (dict): The trigger event payload.
    context (google.cloud.functions.Context): Metadata for the event.
  """
  page_metrics = get_gcs_file_contents(data)
  max_time_meaningful_paint = int(os.environ.get('MAX_TIME_MEANINGFUL_PAINT'))
  analysis_result = analyze_metrics(data, page_metrics,
                                    max_time_meaningful_paint)
  docref = persist(analysis_result, data['name'])
  logging.info('Created new Firestore document %s/%s describing analysis of %s',
               docref.parent.id, docref.id, analysis_result['input_file'])
  • Implante a Função do Cloud analyze:

    gcloud functions deploy analyze \
        --trigger-resource gs://$METRICS_BUCKET \
        --trigger-event google.storage.object.finalize \
        --runtime python37 \
        --source analyzer \
        --env-vars-file env-vars.yaml
    

    A função é acionada por um evento finalize no bucket de métricas, que é enviado sempre que um objeto é criado no bucket. A função usa o ambiente de execução do Python 3.7.

Como alertar sobre falhas

Tipicamente, você toma providências se a análise de métricas indicar uma página com desempenho insatisfatório.

Nesta seção, você cria uma Função do Cloud para enviar uma mensagem a um tópico do Pub/Sub se o desempenho da página for insatisfatório. A função é acionada sempre que um documento é criado na coleção do Firestore. As partes interessadas podem assinar o tópico do Pub/Sub e tomar as medidas adequadas. Por exemplo, um app de suporte pode assinar as mensagens do Pub/Sub e enviar um e-mail, acionar um pager de suporte ou abrir um bug.

No snippet a seguir, do arquivo alerter/main.py, veja a lógica da função:

def generate_alert(data, context):
  """Cloud Function entry point, triggered by a change to a Firestore document.

  If the triggering document indicates a Failed status, send the document to
  configured PubSub topic.

  Args:
    data (dict): The event payload.
    context (google.cloud.functions.Context): Metadata for the event.
  """
  doc_fields = data['value']['fields']
  status = doc_fields['status']['stringValue']
  if 'FAIL' in status:
    global publish_client
    if not publish_client:
      publish_client = pubsub.PublisherClient()

    logging.info('Sending alert in response to %s status in document %s',
                 status, context.resource)
    project = os.environ.get('GCP_PROJECT')
    topic = os.environ.get('ALERT_TOPIC')
    fqtn = 'projects/{}/topics/{}'.format(project, topic)
    msg = json.dumps(data['value']).encode('utf-8')
    publish_client.publish(fqtn, msg)

Observe que o alerta só é enviado quando o campo de status indica uma falha.

  • Implante a Função do Cloud alert:

    gcloud functions deploy alert \
        --trigger-event providers/cloud.firestore/eventTypes/document.create \
        --trigger-resource "projects/$PROJECT/databases/(default)/documents/page-metrics/{any}" \
        --runtime python37 \
        --source alerter \
        --env-vars-file env-vars.yaml \
        --entry-point generate_alert
    

    A função é acionada por um evento document.create na coleção page-metrics do Firestore. O sufixo {any} é um caractere curinga indicando que a função seja acionada sempre que um documento é criado na coleção.

Como programar a análise

É recomendável monitorar regularmente o desempenho da página. Por exemplo, convém analisar uma determinada página a cada hora, a cada dia ou a cada semana. Nesta seção, você cria um job do Cloud Scheduler para executar periodicamente o pipeline de análise acionando a função trace.

O job do Cloud Scheduler é executado usando uma conta de serviço que recebeu o papel de IAM cloudfunctions.invoker necessário para a função trace.

Às vezes, as páginas da Web não respondem corretamente ou solicitam o tempo limite, portanto, as tentativas são inevitáveis com app de análise da Web. Em vista disso, é importante ter uma lógica de repetição no seu app. O Cloud Functions aceita novas tentativas de funções de segundo plano.

As novas tentativas não estão disponíveis para o Cloud Functions acionado por HTTP. Portanto, não é possível usar o Cloud Functions para repetir a função trace. No entanto, o Cloud Scheduler aceita novas tentativas. Para mais informações sobre como configurar parâmetros de repetição, consulte a documentação de RetryConfig.

  1. Verifique se as três Funções do Cloud foram implantadas corretamente e estão exibindo o status ACTIVE:

    gcloud functions list
    
  2. Crie uma nova conta de serviço que será usada como identidade para executar o job do Cloud Scheduler:

    gcloud iam service-accounts create tracer-job-sa
    
  3. Conceda à nova conta de serviço o papel de IAM cloudfunctions.invoker para a função trace:

    gcloud beta functions add-iam-policy-binding trace \
        --role roles/cloudfunctions.invoker \
        --member "serviceAccount:tracer-job-sa@$PROJECT.iam.gserviceaccount.com"
    
  4. Crie um job do Cloud Scheduler:

    gcloud scheduler jobs create http traceWithRetry \
        --uri="https://$REGION-$PROJECT.cloudfunctions.net/trace" \
        --http-method=POST \
        --message-body="{\"url\":\"http://www.example.com\"}" \
        --headers="Content-Type=application/json" \
        --oidc-service-account-email="tracer-job-sa@$PROJECT.iam.gserviceaccount.com" \
        --schedule="0 3 * * *" \
        --time-zone="UTC" \
        --max-retry-attempts=3 \
        --min-backoff=30s
    

    Como o job chamará a função trace acionada por HTTP, o comando especificará o tipo de job como http e fornecerá o URL do gatilho da função como o valor uri. A página a ser analisada, neste caso, www.example.com, é fornecida na sinalização message-body. A sinalização oidc-service-account-email define a conta de serviço a ser usada para autenticação. O comando indica o número de tentativas de usar a sinalização max-retry-attempts, e o valor passado com a sinalização schedule define a programação de execução como 3h UTC todos os dias.

Como verificar resultados

Nesta seção, você verifica o comportamento esperado para as condições de sucesso e falha.

Verificar o sucesso

O job do Cloud Scheduler não será executado até o próximo horário programado, que, neste caso, é 3h UTC. Para ver os resultados imediatamente, acione uma execução manualmente.

  1. Aguarde 90 segundos para que o job do programador seja concluído.
  2. Execute o job do Cloud Scheduler manualmente:

    gcloud scheduler jobs run traceWithRetry
    
  3. Aguarde cerca de 30 segundos para que o pipeline da função seja concluído.

  4. Liste o conteúdo do bucket de métricas para mostrar que as métricas da página foram coletadas:

    gsutil ls -l gs://$METRICS_BUCKET
    
  5. No console do Google Cloud, abra a página do visualizador do Cloud Logging:

    Acessar a página do Logging

    Você verá mensagens de registro de cada uma das três Funções do Cloud: trace, analyze e alert. Pode levar alguns instantes para que os registros apareçam, portanto, talvez seja necessário atualizar o painel de registros.

    Console do Logging sem erros

  6. Anote o código do documento do Firestore, que aparece após o texto Created new Firestore document page-metrics/.

  7. No console do Google Cloud, acesse a página do Firestore:

    Acessar a página do Firestore

  8. Inspecione o documento que contém os resultados da análise. Os valores do documento indicam um status PASS e contêm as métricas de desempenho mais recentes da página.

  9. No Cloud Shell, verifique se alguma mensagem de alerta foi enviada ao tópico do Pub/Sub ao tentar extrair uma mensagem da assinatura:

    gcloud pubsub subscriptions pull \
        projects/$PROJECT/subscriptions/performance-alerts-sub \
        --auto-ack
    

    Você não vê nenhum item listado.

Verificar falha

  1. Acione manualmente a função de rastreamento. Dessa vez, você fornece a página Tutoriais do Google Cloud como URL. Nessa página, há muito conteúdo dinâmico que aumenta o tempo de carregamento da página acima do limite máximo esperado.

    gcloud functions call trace \
        --data='{"url":"https://cloud.google.com/docs/tutorials"}'
    

    Por ter o papel de IAM Owner ou Editor do projeto, você tem permissões suficientes para invocar a função.

  2. Aguarde cerca de 30 segundos para que o pipeline da função seja concluído.

  3. Liste o conteúdo do bucket de métricas para verificar se houve coleta de outras métricas:

    gsutil ls -l gs://$METRICS_BUCKET
    

    Agora você vê dois itens em cada bucket.

  4. No console do Google Cloud, acesse a página do visualizador do Cloud Logging e filtre os registros do Cloud Functions:

    Acessar a página do Logging

    Veja um erro da função analyze, indicando que a página excedeu o tempo máximo de carregamento permitido. Novamente, talvez seja necessário atualizar o painel de registros para ver as mensagens mais recentes.

    Console do Logging mostrando erros

  5. Anote o código do documento do Firestore.

  6. No console do Google Cloud, acesse a página do Firestore:

    Acessar a página do Firestore

  7. Encontre o documento que descreve a análise que falhou.

    O campo de status é marcado como FAIL.

  8. No Cloud Shell, verifique se uma mensagem de alerta foi enviada para o tópico do Pub/Sub ao extrair uma mensagem da assinatura.

    gcloud pubsub subscriptions pull \
        projects/$PROJECT/subscriptions/performance-alerts-sub \
        --auto-ack
    

    Desta vez, você vê o conteúdo da mensagem.

Limpeza

Exclua o projeto

  1. No Console do Google Cloud, acesse a página Gerenciar recursos.

    Acessar "Gerenciar recursos"

  2. Na lista de projetos, selecione o projeto que você quer excluir e clique em Excluir .
  3. Na caixa de diálogo, digite o ID do projeto e clique em Encerrar para excluí-lo.

A seguir