Crea perfiles de aplicaciones Python

En esta página, se describe cómo modificar tu aplicación de Python para capturar datos de creación de perfiles y enviarlos a tu proyecto de Google Cloud. Para obtener información general sobre la creación de perfiles, consulta el artículo sobre conceptos de creación de perfiles.

Tipos de perfiles para Python:

  • Tiempo de CPU
  • Tiempo real (subproceso principal)

Versiones del lenguaje Python compatibles:

  • Python 3.6 o una versión superior.

Versiones compatibles del agente de generación de perfiles:

  • Se admite la versión más reciente del agente. Por lo general, no se admiten las actualizaciones de más de un año. Te recomendamos usar la versión más reciente del agente.

Sistemas operativos compatibles:

  • Linux. La creación de perfiles de aplicaciones de Python es compatible con kernels de Linux cuya biblioteca C estándar se implementa con glibc o musl. Para obtener información de configuración específica de los kernels Linux Alpine, consulta la sección sobre ejecución en Linux Alpine.

Entornos compatibles:

Habilita la API de Profiler

Antes de usar el agente de generación de perfiles, asegúrate de que la API de Profiler subyacente esté habilitada. Puedes verificar el estado de la API y habilitarla, si es necesario, con Google Cloud CLI o la consola de Google:

CLI de gcloud

  1. Si aún no instalaste Google Cloud CLI en tu estación de trabajo, consulta la documentación de Google Cloud CLI.

  2. Ejecuta el siguiente comando:

    gcloud services enable cloudprofiler.googleapis.com
    

Para obtener más información, consulta gcloud services

Consola de Google Cloud

  1. Enable the required API.

    Enable the API

  2. Si se muestra API habilitada, la API ya está habilitada. De lo contrario, haz clic en el botón Habilitar.

Otorga un rol de IAM a la cuenta de servicio

Si implementas tu aplicación en recursos de Google Cloud y usas la cuenta de servicio predeterminada y no modificaste los roles otorgados a esa cuenta de servicio, puedes omitir esta sección.

Si realizas alguna de las siguientes acciones, debes otorgarle a la cuenta de servicio el rol de IAM de agente de Cloud Profiler (roles/cloudprofiler.agent):

  1. Estás usando la cuenta de servicio predeterminada, pero modificaste sus otorgamientos de roles.
  2. Estás usando una cuenta de servicio creada por el usuario.
  3. Si usas Workload Identity, otorga el rol de Agente de Cloud Profiler a la cuenta de servicio de Kubernetes.

Puedes otorgar un rol de IAM a una cuenta de servicio mediante la consola de Google Cloud o Google Cloud CLI. Por ejemplo, puedes usar el comando gcloud projects add-iam-policy-binding:

gcloud projects add-iam-policy-binding GCP_PROJECT_ID \
    --member serviceAccount:MY_SVC_ACCT_ID@GCP_PROJECT_ID.iam.gserviceaccount.com \
    --role roles/cloudprofiler.agent

Antes de usar el comando anterior, reemplaza lo siguiente:

  • GCP_PROJECT_ID: ID del proyecto
  • MY_SVC_ACCT_ID: Es el nombre de la cuenta de servicio.

Para obtener información detallada, consulta Administra el acceso a proyectos, carpetas y organizaciones.

Usa Cloud Profiler

Para obtener prácticas recomendadas sobre el uso de Python, consulta la sección sobre cómo configurar un entorno de desarrollo de Python.

Compute Engine

Para Compute Engine, haz lo siguiente:

  1. Instala el compilador C/C++ y las herramientas de desarrollo:

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

    sudo apt-get install -y python3-pip
    
  3. Instala el paquete de Profiler:

    pip3 install google-cloud-profiler
    
  4. Importa el módulo googlecloudprofiler y llama a la función googlecloudprofiler.start lo antes posible en tu código de inicialización:

    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

    Debes especificar el parámetro service en tu función start. Para filtrar por versión de la aplicación en la interfaz de Profiler, especifica el parámetro service_version. Para obtener información sobre solución de problemas y excepciones, consulta la sección solución de problemas.

GKE

En GKE, sigue estos pasos:

  1. Modifica tu Dockerfile para instalar el paquete de Profiler:

    FROM python:3
    ...
    RUN apt-get update && apt-get install -y build-essential python3-pip
    RUN pip3 install google-cloud-profiler
    
  2. Importa el módulo googlecloudprofiler y llama a la función googlecloudprofiler.start lo antes posible en tu código de inicialización:

    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

    Debes especificar el parámetro service en tu función start. Para filtrar por versión de la aplicación en la interfaz de Profiler, especifica el parámetro service_version. Para obtener información sobre solución de problemas y excepciones, consulta la sección sobre solución de problemas.

Entorno flexible

Para el entorno flexible de App Engine, haz lo siguiente:

  1. Agrega google-cloud-profiler a tu archivo requirements.txt.

  2. Importa el módulo googlecloudprofiler y llama a la función googlecloudprofiler.start lo antes posible en tu código de inicialización.

Para App Engine, service y service_version se derivan de tu entorno operativo. Para obtener información sobre solución de problemas y excepciones, consulta la sección sobresolución de problemas.

Entorno estándar

Para el entorno estándar de App Engine, que requiere que uses el entorno de ejecución de Python 3, haz lo siguiente:

  1. Agrega google-cloud-profiler a tu archivo requirements.txt.

  2. Importa el módulo googlecloudprofiler y llama a la función googlecloudprofiler.start lo antes posible en tu código de inicialización.

Para App Engine, service y service_version se derivan de tu entorno operativo. Para obtener información sobre solución de problemas y excepciones, consulta la sección sobre solución de problemas.

Función start

La función googlecloudprofiler.start crea un subproceso de daemon que recopila y sube perfiles de forma continua. Debes llamar a start una vez y lo antes posible en tu aplicación.

Parámetro Descripción
service1 El nombre del servicio para el que se crean perfiles (obligatorio). Para conocer las restricciones en el nombre del servicio, consulta la sección sobre argumentos de la versión y del nombre del servicio.
service_version1 La versión del servicio para la que se crean perfiles (opcional). Para conocer las restricciones en la versión del servicio, consulta la sección sobre argumentos de la versión y del nombre del servicio.
verbose El nivel de registro (opcional). Para obtener detalles sobre los niveles de registro, consulta la sección sobre registro de agente.

El valor predeterminado es 0 (Error).
project_id2 Tu ID del proyecto de Google Cloud (opcional).
disable_cpu_profiling Para inhabilitar la creación de perfiles de tiempo de CPU, configura disable_cpu_profiling=True.

Este parámetro solo es compatible con Python 3.2 y versiones posteriores. Para todas las demás versiones de Python, no se admite la creación de perfiles de tiempo de CPU y este parámetro se ignora.

El valor predeterminado es falso.
disable_wall_profiling Para inhabilitar la creación de perfiles de tiempo, configura disable_wall_profiling=True (opcional).

Este parámetro es compatible con Python 3.6 y versiones posteriores. Para todas las demás versiones de Python, no se admite la creación de perfiles de tiempo y este parámetro se ignora.

Para conocer las restricciones en la función start cuando la creación de perfiles de tiempo está habilitada, consulta la sección sobre limitaciones.

El valor predeterminado es falso.

1 Solo para Compute Engine y GKE. Para App Engine, el valor se deriva del entorno.
2 Para Google Cloud, el valor se deriva del entorno. Para entornos que no son de Google Cloud, debes proporcionar un valor. Para obtener más información, consulta la sección sobre cómo crear perfiles de aplicaciones que se ejecutan fuera de Google Cloud.

Analiza datos

Una vez que Profiler haya recopilado los datos, podrás verlos y analizarlos con la interfaz de Profiler.

En la consola de Google Cloud, ve a la página Profiler:

Ve a Profiler.

También puedes usar la barra de búsqueda para encontrar esta página.

Argumentos de versión y nombre del servicio

Cuando cargas el agente de Profiler, especificas un argumento de nombre del servicio y un argumento de la versión del servicio opcional para configurarlo.

El nombre del servicio permite que Profiler recopile datos de generación de perfiles para todas las réplicas de ese servicio. El servicio del generador de perfiles garantiza una tasa promedio de recopilación de un perfil por minuto para cada nombre de servicio en cada combinación de zonas y versiones del servicio.

Por ejemplo, si tienes un servicio con dos versiones que se ejecutan en réplicas en tres zonas, el generador de perfiles creará un promedio de 6 perfiles por minuto para ese servicio.

Si usas nombres de servicio diferentes para tus réplicas, se generarán los perfiles del servicio con más frecuencia que la necesaria y con una sobrecarga más alta.

Cuando selecciones un nombre de servicio, ten en cuenta lo siguiente:

  • Elige un nombre que represente de forma clara el servicio en la arquitectura de tu aplicación. La elección del nombre del servicio es menos importante si solo ejecutas un único servicio o aplicación. Por ejemplo, es más importante si tu aplicación se ejecuta como un conjunto de microservicios.

  • Asegúrate de no usar ningún valor específico del proceso, como un ID de proceso, en la string de nombre del servicio.

  • La string de nombre del servicio debe coincidir con esta expresión regular:

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

Un buen lineamiento es usar una string estática, como imageproc-service, como nombre del servicio.

La versión del servicio es opcional. Si especificas la versión del servicio, Profiler puede agregar información de generación de perfiles de varias instancias y mostrarla correctamente. Se puede usar para marcar diferentes versiones de tus servicios a medida que se implementan. La IU de Profiler te permite filtrar los datos por versión del servicio. De esta manera, puedes comparar el rendimiento de las versiones anteriores y más recientes del código.

El valor del argumento de la versión del servicio es una string de formato libre, pero los valores de este argumento suelen verse como números de versión, por ejemplo, 1.0.0 o 2.1.2.

Registro de agente

De forma predeterminada, el agente de creación de perfiles registra los mensajes con un nivel de gravedad de error. A fin de configurar el agente para que registre mensajes con niveles de gravedad más bajos, especifica el parámetro verbose cuando inicies el agente. Hay cuatro valores admitidos para verbose:

  • 0: error
  • 1: advertencia
  • 2: mensajes informativos
  • 3: depurar

Si configuras el parámetro verbose para 1 en la llamada a start, los mensajes con un nivel de gravedad Warning o Error se registran, mientras que los mensajes Informational y Debug se ignoran.

Para registrar todos los mensajes, configura verbose en 3 cuando inicies el agente:

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

Soluciona problemas

En esta sección se enumeran las limitaciones, las excepciones y los problemas conocidos específicos de la generación de perfiles de aplicaciones de Python. Consulta la página Solución de problemas a fin de obtener ayuda para resolver problemas comunes.

Limitaciones

Tipo de perfil Restricciones y limitaciones
Tiempo
  • Creación de perfiles de subprocesos principales únicamente.
  • La función start del perfil se debe llamar desde el subproceso principal.
  • El controlador de señal de Profiler solo se ejecuta en el subproceso principal. Si el subproceso principal no se puede ejecutar, no se capturan los datos de creación de perfiles.

Excepciones

Error Causa Solución
Se muestra NotImplementedError durante start Aplicación ejecutada en un entorno que no es de Linux.
  • Ejecuta tu aplicación en un entorno Linux.
Se muestra ValueError durante start Los argumentos de la función start no son válidos, la información necesaria no puede determinarse a partir de las variables de entorno, los argumentos o la creación de perfiles si tanto la creación de perfiles de tiempo de CPU como la de tiempo se inhabilitan.
  • Asegúrate de que el nombre y la versión del servicio cumplan con los requisitos definidos en la sección sobre argumentos de la versión y del nombre del servicio.
  • Si la creación de perfiles de tiempo está habilitada, asegúrate de que se llame a start desde el subproceso principal.
  • Asegúrate de usar una versión compatible de Python y de que la creación de perfiles de tiempo de CPU o tiempo esté habilitada. Para obtener más información, consulta la función start.
  • Verifica que hayas especificado el parámetro project_id en start si estás realizando la ejecución fuera de Google Cloud. Para obtener más información, consulta la función start.

Problemas conocidos

Comportamiento Causa Solución
No tienes ningún dato de perfil o habilitaste un nuevo tipo de perfil y faltan esos datos. Las causas comunes están relacionadas con la configuración. Consulta Solución de problemas.
Estás usando uWSGI y no tienes tiempo de CPU ni datos de perfil de tiempo para todos los procesos.

Cuando uWSGI usa varios trabajadores para controlar las solicitudes, el comportamiento predeterminado es realizar la inicialización de la aplicación solo en el proceso principal. Los procesos bifurcados no realizan la secuencia de inicialización.

Si configuras el agente de creación de perfiles en la secuencia de inicialización de tu aplicación, por ejemplo, en AppConfig.ready() en una aplicación de Django, el agente de generación de perfiles no se configurará para los procesos bifurcados.

Para realizar la inicialización de la aplicación en todos los procesos de los trabajadores, configura la marca lazy-apps como true.

Consulta el siguiente tema de esta tabla para ver un problema relacionado.

Estás usando uWSGI y no tienes datos de perfil de tiempo, pero sí datos de perfil de tiempo de CPU.

El generador de perfiles de tiempo depende del módulo de indicador de Python. Cuando el intérprete de Python se compila con compatibilidad de subprocesos, la configuración predeterminada inhabilita el manejo de indicadores personalizados para los procesos bifurcados.

En el caso de las aplicaciones de uWSGI, habilita el control de indicadores personalizados. Para ello, configura la marca py-call-osafterfork como true.

Consulta el tema anterior de esta tabla para ver un problema relacionado.

Después de habilitar el generador de perfiles, el registro de errores contiene entradas nuevas:

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

Errores de GitHub

Tu aplicación registrada con el descriptor de archivo de activación de señal, signal.set_wakeup_fd. De forma predeterminada, si se llena el búfer del descriptor de archivo, se registra una advertencia en stderr.

Cuando Cloud Profiler recopila perfiles, activa señales con alta frecuencia. Este comportamiento puede hacer que el búfer del descriptor de archivo se llene.

Si tu aplicación puede ejecutarse de manera segura cuando se pierden los indicadores, puedes usar Cloud Profiler. Si usas Python 3.7 o una versión posterior y deseas inhabilitar los mensajes de advertencia, pasa warn_on_full_buffer=False como un parámetro a signal.set_wakeup_fd.

Si tu aplicación no se puede ejecutar de forma segura cuando se pierden los indicadores, te recomendamos que dejes de usar Cloud Profiler. El uso continuo puede causar una pérdida de números de señal y entradas excesivas en el registro de errores.

Ejecuta con Linux Alpine

El agente de generación de perfiles de Python para Linux Alpine solo es compatible con las configuraciones de Google Kubernetes Engine.

Para compilar el agente de creación de perfiles de Python, debes instalar el paquete build-base. Para usar el agente de creación de perfiles de Python en Alpine sin instalar dependencias adicionales en la imagen final de Alpine, puedes usar una compilación en dos etapas y compilar el agente de creación de perfiles de Python en la primera etapa. Por ejemplo, la siguiente imagen de Docker usa una compilación de varias etapas para compilar e instalar el agente de creación de perfiles de 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

Error de autenticación

Si usas imágenes de Docker que se ejecutan con Linux Alpine (como golang:alpine o solo alpine), es posible que veas el siguiente error de autenticación:

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

Ten en cuenta que, para ver el error, debes tener habilitado el registro de agente.

El error indica que las imágenes de Docker con Linux Alpine no tienen los certificados SSL raíz instalados de forma predeterminada. Esos certificados son necesarios para que el agente de creación de perfiles se comunique con la API de Profiler. Para resolver este error, agrega el siguiente comando apk a tu Dockerfile:

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

Luego, debes volver a compilar y volver a implementar tu aplicación.

¿Qué sigue?