Como criar perfis de aplicativos Python

Esta página explica como modificar seu aplicativo Python para capturar dados de criação de perfil e enviá-los para seu projeto do Google Cloud. Para informações gerais sobre criação de perfil, consulte Conceitos de criação de perfil.

Tipos de perfil para Python:

  • Tempo de CPU
  • Tempo decorrido (linha de execução principal)

Versões compatíveis com a linguagem Python:

  • Python 3.6 ou posterior.

Versões compatíveis com o agente de criação de perfil:

  • A versão mais recente do agente é compatível. Em geral, lançamentos com mais de um ano não são compatíveis. Recomendamos que você use a versão do agente lançada mais recentemente.

Sistemas operacionais compatíveis:

  • Linux. A criação de perfil de aplicativos Python é compatível com kernels do Linux em que a biblioteca C padrão foi implementada com glibc ou musl. Saiba mais sobre informações de configuração específicas aos kernels do Alpine Linux em Como executar no Alpine Linux.

Ambientes compatíveis:

Como ativar a API Profiler

Antes de usar o agente de criação de perfil, garanta que a API Profiler subjacente esteja ativada. É possível verificar o status da API e ativá-la, se necessário, usando a CLI do Google Cloud ou o Console do Google Cloud:

CLI da gcloud

  1. Se você ainda não instalou a CLI do Google Cloud na sua estação de trabalho, consulte a documentação da CLI do Google Cloud.

  2. Execute este comando:

    gcloud services enable cloudprofiler.googleapis.com
    

Para ver mais informações, consulte gcloud services.

Console do Google Cloud

  1. No painel de navegação do console do Google Cloud, selecione APIs e serviços, clique em Ativar APIs e serviços e ative a API Cloud Profiler:

    Acessar as configurações da API Profiler

  2. Se a mensagem API ativada for exibida, quer dizer que a API já está ativada. Caso contrário, clique no botão Ativar.

Como usar o Cloud Profiler

Para práticas recomendadas usando Python, acesse Como configurar um ambiente de desenvolvimento Python.

Compute Engine

No Compute Engine:

  1. Instale o compilador C/C ++ e as ferramentas de desenvolvimento:

    sudo apt-get install -y build-essential
    
  2. Instale o pip:

    sudo apt-get install -y python3-pip
    
  3. Instale o pacote do Profiler:

    pip3 install google-cloud-profiler
    
  4. Importe o módulo googlecloudprofiler e chame a função googlecloudprofiler.start o quanto antes no código de inicialização:

    import googlecloudprofiler
    
    def main():
        # Profiler initialization. It starts a daemon thread which continuously
        # collects and uploads profiles. Best done as early as possible.
        try:
            googlecloudprofiler.start(
                service="hello-profiler",
                service_version="1.0.1",
                # verbose is the logging level. 0-error, 1-warning, 2-info,
                # 3-debug. It defaults to 0 (error) if not set.
                verbose=3,
                # project_id must be set if not running on GCP.
                # project_id='my-project-id',
            )
        except (ValueError, NotImplementedError) as exc:
            print(exc)  # Handle errors here

    Especifique o parâmetro service na função start. Para filtrar pela versão do aplicativo na interface do Profiler, especifique o parâmetro service_version. Saiba mais sobre solução de problemas e exceções em Como solucionar problemas.

GKE;

Para o GKE:

  1. Modifique o Dockerfile para instalar o pacote do Profiler:

    FROM python:3
    ...
    RUN apt-get update && apt-get install -y build-essential python3-pip
    RUN pip3 install google-cloud-profiler
    
  2. Importe o módulo googlecloudprofiler e chame a função googlecloudprofiler.start o quanto antes no código de inicialização:

    import googlecloudprofiler
    
    def main():
        # Profiler initialization. It starts a daemon thread which continuously
        # collects and uploads profiles. Best done as early as possible.
        try:
            googlecloudprofiler.start(
                service="hello-profiler",
                service_version="1.0.1",
                # verbose is the logging level. 0-error, 1-warning, 2-info,
                # 3-debug. It defaults to 0 (error) if not set.
                verbose=3,
                # project_id must be set if not running on GCP.
                # project_id='my-project-id',
            )
        except (ValueError, NotImplementedError) as exc:
            print(exc)  # Handle errors here

    Especifique o parâmetro service na função start. Para filtrar pela versão do aplicativo na interface do Profiler, especifique o parâmetro service_version. Saiba mais sobre solução de problemas e exceções em Como solucionar problemas.

Ambiente flexível

No ambiente flexível do App Engine, faça o seguinte:

  1. Adicione google-cloud-profiler ao seu arquivo requirements.txt.

  2. Importe o módulo googlecloudprofiler e chame a função googlecloudprofiler.start o quanto antes no código de inicialização.

No App Engine, service e service_version são derivados do seu ambiente operacional. Saiba mais sobre solução de problemas e exceções em Como solucionar problemas.

Ambiente padrão

No ambiente padrão do App Engine, que requer o ambiente de execução do Python 3, faça o seguinte:

  1. Adicione google-cloud-profiler ao seu arquivo requirements.txt.

  2. Importe o módulo googlecloudprofiler e chame a função googlecloudprofiler.start o quanto antes no código de inicialização.

No App Engine, service e service_version são derivados do seu ambiente operacional. Saiba mais sobre solução de problemas e exceções em Como solucionar problemas.

Função start

A função googlecloudprofiler.start cria uma linha de execução do daemon que coleta e faz upload de perfis continuamente. Você deve chamar start uma vez e o mais cedo possível no seu aplicativo.

Parâmetro Descrição
service1 (Obrigatório) O nome do serviço para o qual você está criando um perfil. Para ver restrições no nome do serviço, consulte Argumentos de versão e nome de serviço.
service_version1 (Opcional) A versão do serviço para o qual você está criando um perfil. Para ver restrições na versão do serviço, consulte Nome do serviço e argumentos de versão.
verbose (Opcional) O nível de geração de registros. Para detalhes sobre ele, consulte Geração de registros do agente.

O valor padrão é 0 (Erro).
project_id2 (Opcional) O ID do projeto do Google Cloud.
disable_cpu_profiling (Opcional) Para desativar a criação de perfil de tempo de CPU, defina disable_cpu_profiling=True.

Este parâmetro é compatível apenas com o Python 3.2 e posterior. Em todas as outras versões do Python, a criação de perfil do tempo da CPU não é compatível, e esse parâmetro é ignorado.

O valor padrão é Falso.
disable_wall_profiling (Opcional) Para desativar a criação de perfil do tempo decorrido, defina disable_wall_profiling=True.

Esse parâmetro é compatível com Python 3.6 e versões mais recentes. Em todas as outras versões do Python, a criação de perfil do tempo decorrido não é compatível, e esse parâmetro é ignorado.

Veja as restrições na função start quando a criação de perfil do tempo decorrido está ativada em Limitações.

O valor padrão é Falso.

1 Somente para o Compute Engine e o GKE. Para o App Engine, o valor é derivado do ambiente.
2 Para o Google Cloud, o valor é derivado do ambiente. Para ambientes que não são do Google Cloud, você precisa fornecer um valor. Saiba mais em Como criar perfis de aplicativos em execução fora do Google Cloud.

Análise de dados

Depois que o Profiler coletar dados, será possível visualizá-los e analisá-los usando a interface dele.

No painel de navegação do console do Google Cloud, selecione Profiler:

Acesse o Profiler

Argumentos de versão e nome de serviço

Ao carregar o agente do Profiler, você especifica um argumento de nome de serviço e um opcional de versão para configurá-lo.

Com o nome de serviço, o Profiler pode coletar dados de criação de perfil de todas as réplicas desse serviço. O criador de perfil garante uma taxa de coleta de um perfil por minuto, em média. Isso é para todos os nomes de serviço em cada combinação de zona e versão.

Por exemplo, se você tiver um serviço com duas versões executadas em réplicas em três zonas, o criador de perfil produzirá uma média de seis perfis por minuto para esse serviço.

Se você usar nomes de serviço diferentes nas réplicas, o serviço terá perfis criados com mais frequência do que o necessário, com uma sobrecarga correspondente maior.

Ao selecionar um nome de serviço:

  • escolha um que represente claramente o serviço na arquitetura do aplicativo. Essa seleção não é tão importante se você executa apenas um serviço ou aplicativo. Ela é mais importante se o aplicativo é executado como um conjunto de microsserviços, por exemplo;

  • não use nenhum valor específico do processo, como o código, na string do nome de serviço;

  • a string do nome de serviço precisa corresponder a esta expressão regular:

    ^[a-z0-9]([-a-z0-9_.]{0,253}[a-z0-9])?$

Uma boa diretriz é usar uma string estática como imageproc-service como o nome do serviço.

A versão de serviço é opcional. Se você especificá-la, o Profiler poderá agregar informações de criação de perfil de várias instâncias e exibi-las corretamente. É possível usá-la para marcar diferentes versões dos serviços conforme eles são implantados. Com a IU do Profiler, você filtra os dados por versão de serviço. Assim, é possível comparar o desempenho de versões mais antigas e mais recentes do código.

O valor do argumento da versão do serviço é uma string de formato livre. No entanto, os valores desse argumento geralmente se parecem com números de versão. Por exemplo, 1.0.0 ou 2.1.2.

Geração de registros do agente

Por padrão, o agente de criação de perfil registra mensagens com um nível de gravidade de error. É possível configurar o agente para registrar mensagens com níveis de gravidade mais baixos especificando o parâmetro verbose ao iniciar o agente. Há quatro valores compatíveis com verbose:

  • 0: erro
  • 1: aviso
  • 2: mensagem informativa
  • 3: depuração

Se você definir o parâmetro verbose para 1 na sua chamada para start, as mensagens com um nível de gravidade de Warning ou Error serão registrados, enquanto as mensagens Informational e Debug serão ignoradas.

Para registrar todas as mensagens, defina verbose como 3 ao iniciar o agente:

googlecloudprofiler.start(service='service_name', verbose=3)

Solução de problemas

Nesta seção, listamos as limitações, exceções e problemas conhecidos específicos da criação de perfil de aplicativos Python. Consulte Solução de problemas para conseguir ajuda com problemas comuns.

Limitações

Tipo de perfil Restrições e limitações
Tempo decorrido real
  • Somente criação de perfil na linha de execução principal.
  • A função do perfil start precisa ser chamada a partir da linha de execução principal.
  • O gerenciador de sinal do Profiler é executado somente na linha de execução principal. Se não for possível executar essa linha de execução, nenhum dado de criação de perfil será coletado.

Exceções

Erro Causa Solução
NotImplementedError gerado durante start Aplicativo executado em um ambiente que não é Linux.
  • Execute o aplicativo em um ambiente Linux.
ValueError gerado durante start Os argumentos da função start são inválidos, não é possível determinar as informações necessárias a partir das variáveis de ambiente e dos argumentos nem da criação de perfil se a criação de perfil de tempo de CPU e de tempo decorrido estiverem desativadas.
  • Garanta que o nome e a versão do serviço atendam aos requisitos definidos em Argumentos de versão e nome de serviço.
  • Se a criação de perfil de tempo decorrido estiver ativada, start deverá ser chamada a partir da linha de execução principal.
  • Verifique se você usa uma versão compatível do Python, e se a criação de perfil dos tipos "Tempo de CPU" e "tempo decorrido" está ativada. Para saber mais, veja a função start.
  • Verifique se você especificou o parâmetro project_id para start se estiver executando fora do Google Cloud. Para saber mais, veja a função start.

Problemas conhecidos

Comportamento Causa Solução
Você não tem dados de perfil ou ativou um novo tipo de perfil e não há dados de perfil. As causas comuns estão relacionadas à configuração. Consulte Solução de problemas.
Você está usando uWSGI (em inglês) e não tem tempo de CPU e dados de perfil do tempo decorrido para todos os processos.

Quando o uWSGI usa vários workers para processar solicitações, o comportamento padrão é executar a inicialização do aplicativo apenas no processo principal ("mestre"). Os processos bifurcados não executam a sequência de inicialização.

Se você configurar o agente de criação de perfil na sequência de inicialização do aplicativo, por exemplo, no AppConfig.ready() em um aplicativo Django, o efeito será que o agente de criação de perfil não estará configurado para os processos bifurcados.

Para executar a inicialização do aplicativo em todos os processos do worker, defina a sinalização lazy-apps (em inglês) como true.

Consulte o próximo tópico nesta tabela para ver um problema relacionado.

Você está usando uWSGI (em inglês) e não tem dados de perfil do tempo decorrido, mas tem dados de perfil de tempo de CPU.

O criador de perfil do tempo decorrido depende do módulo de sinal do Python. Quando o interpretador de Python é compilado com suporte à linha de execução, a configuração padrão desativa o processamento de sinal personalizado para processos bifurcados.

Para aplicativos uWSGI, ative o processamento de sinal personalizado ao definir a sinalização py-call-osafterfork (em inglês) como true.

Consulte o tópico anterior nesta tabela para ver um problema relacionado.

Depois de ativar o criador de perfil, o registro de erros conterá novas entradas:

BlockingIOError: [Errno 11] Resource temporarily unavailable Exception ignored when trying to write to the signal wakeup fd

Problema no GitHub

Seu aplicativo registrado com o descritor do arquivo de ativação do sinal, signal.set_wakeup_fd. Por padrão, se o buffer do descritor do arquivo for preenchido, um aviso será registrado no stderr.

O Cloud Profiler aciona sinais com alta frequência quando coleta perfis. Esse comportamento pode fazer com que o buffer do descritor do arquivo fique cheio.

Se seu aplicativo puder ser executado com segurança quando os sinais forem perdidos, use o Cloud Profiler. Se você estiver usando o Python 3.7 ou posterior e quiser desativar as mensagens de aviso, transmita warn_on_full_buffer=False como um parâmetro para signal.set_wakeup_fd.

Se seu aplicativo não puder ser executado com segurança quando os sinais forem perdidos, recomendamos que você pare de usar o Cloud Profiler. O uso contínuo pode causar a perda de números de sinal e excesso de entradas no registro de erros.

Execução com o Alpine Linux

O agente de criação de perfil do Python para Alpine Linux é compatível apenas com as configurações do Google Kubernetes Engine.

Para criar o agente de criação de perfil do Python, instale o pacote build-base. Para usar o agente de criação de perfil do Python no Alpine sem instalar outras dependências na imagem Alpine final, use um build de dois estágios e compile o agente de criação de perfil do Python na primeira etapa. Por exemplo, a imagem do Docker a seguir usa um build de vários estágios para compilar e instalar o agente de criação de perfil do Python:

FROM python:3.7-alpine as builder

# Install build-base to allow for compilation of the profiling agent.
RUN apk add --update --no-cache build-base

# Compile the profiling agent, generating wheels for it.
RUN pip3 wheel --wheel-dir=/tmp/wheels google-cloud-profiler

FROM python:3.7-alpine

# Copy over the directory containing wheels for the profiling agent.
COPY --from=builder /tmp/wheels /tmp/wheels

# Install the profiling agent.
RUN pip3 install --no-index --find-links=/tmp/wheels google-cloud-profiler

# Install any other required modules or dependencies, and copy an app which
# enables the profiler as described in "Enable the profiler in your
# application".
COPY ./bench.py .

# Run the application when the docker image is run, using either CMD (as is done
# here) or ENTRYPOINT.
CMD python3 -u bench.py

Erro de autenticação

Se você usar imagens do Docker executadas com o Linux Alpine (como golang:alpine ou apenas alpine), talvez veja o seguinte erro de autenticação:

connection error: desc = "transport: authentication handshake failed: x509: failed to load system roots and no roots provided"

Para ver o erro, você precisa ativar a geração de registros do agente.

O erro indica que as imagens do Docker com o Alpine Linux não têm os certificados SSL raiz instalados por padrão. Esses certificados são necessários para que o agente de criação de perfil se comunique com a API Profiler. Para resolver esse erro, adicione o seguinte comando apk ao seu Dockerfile:

FROM alpine
...
RUN apk add --no-cache ca-certificates

Depois, será necessário recriar e reimplantar o aplicativo.

A seguir