Crear perfiles de aplicaciones Python

En esta página se describe cómo modificar tu aplicación 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 Conceptos de la creación de perfiles.

.

Tipos de perfiles de Python:

  • Tiempo de CPU
  • Tiempo real (hilo principal)

Versiones de lenguaje Python compatibles:

  • Python 3.6 a 3.11.0.

Versiones compatibles del agente de creación de perfiles:

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

Sistemas operativos compatibles:

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

Entornos admitidos:

Habilitar la API Profiler

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

CLI de gcloud

  1. Si aún no has instalado 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.

Google Cloud consola

  1. Enable the required API.

    Roles required to enable APIs

    To enable APIs, you need the Service Usage Admin IAM role (roles/serviceusage.serviceUsageAdmin), which contains the serviceusage.services.enable permission. Learn how to grant roles.

    Enable the API

  2. Si se muestra API habilitada, significa que la API ya está habilitada. Si no es así, haz clic en el botón Habilitar.

Asignar un rol de gestión de identidades y accesos a una cuenta de servicio

Si vas a implementar tu aplicación en recursos de Google Cloud y usas la cuenta de servicio predeterminada sin haber modificado las concesiones de roles de esa cuenta, puedes saltarte esta sección.

Si haces alguna de las siguientes acciones, debes conceder a la cuenta de servicio el rol de gestión de identidades y accesos Agente de Cloud Profiler (roles/cloudprofiler.agent):

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

Para asignar un rol de gestión de identidades y accesos a una cuenta de servicio, puedes usar laGoogle Cloud consola o la CLI de Google Cloud. 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, sustituye lo siguiente:

  • GCP_PROJECT_ID: tu ID de proyecto.
  • MY_SVC_ACCT_ID: el nombre de tu cuenta de servicio.

Para obtener información detallada, consulta el artículo Gestionar el acceso a proyectos, carpetas y organizaciones.

Usar Cloud Profiler

Para consultar las prácticas recomendadas de Python, ve a Configurar un entorno de desarrollo de Python.

Compute Engine

En Compute Engine, haga lo siguiente:

  1. Instala el compilador de 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 Profiler:

    pip3 install google-cloud-profiler
    
  4. Importa el módulo googlecloudprofiler y llama a la función googlecloudprofiler.start lo antes posible en el 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

    Debe especificar el parámetro service en la función start. Para filtrar por la versión de la aplicación en la interfaz del generador de perfiles, especifica el parámetro service_version. Para obtener información sobre la solución de problemas y las excepciones, consulta la sección Solución de problemas.

GKE

En GKE, haz lo siguiente:

  1. Modifica tu Dockerfile para instalar el paquete 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 el 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

    Debe especificar el parámetro service en la función start. Para filtrar por la versión de la aplicación en la interfaz del generador de perfiles, especifica el parámetro service_version. Para obtener información sobre la solución de problemas y las excepciones, consulta la sección Solución de problemas.

Entorno flexible

En el entorno flexible de App Engine, haga lo siguiente:

  1. Añade 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.

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

Entorno estándar

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

  1. Añade 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.

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

start función

La función googlecloudprofiler.start crea un hilo de daemon que recoge y sube perfiles continuamente. Debes llamar a start una vez y lo antes posible en tu aplicación.

Parámetro Descripción
service1 Obligatorio. Nombre del servicio cuyo perfil se está creando. Para ver las restricciones del nombre del servicio, consulta Argumentos de nombre y versión del servicio.
service_version1 (Opcional) La versión del servicio cuyo perfil se está creando. Para ver las restricciones de la versión del servicio, consulta Argumentos de nombre y versión del servicio.
verbose (Opcional) El nivel de registro. Para obtener más información sobre los niveles de registro, consulta Registro de agentes.

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

Este parámetro es compatible con las versiones de Python de la 3.2 a la 3.11.0. En el resto de las 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 False.
disable_wall_profiling (Opcional) Para inhabilitar la creación de perfiles de Wall, define disable_wall_profiling=True.

Este parámetro es compatible con las versiones de Python de la 3.6 a la 3.11.0. En el resto de las versiones de Python, no se admite la creación de perfiles de tiempo de espera y este parámetro se ignora.

Para ver las restricciones de la función start cuando el perfil de muro está habilitado, consulta Limitaciones.

El valor predeterminado es False.

1 Solo para Compute Engine y GKE. En el caso de App Engine, el valor se deriva del entorno.
2 En el caso de Google Cloud, el valor se deriva del entorno. En los entornos que no sean deGoogle Cloud , debe proporcionar un valor. Para obtener información, consulta el artículo sobre crear perfiles de aplicaciones que se ejecutan fuera de Google Cloud.

Análisis de datos

Una vez que Profiler haya recogido datos, podrá verlos y analizarlos mediante la interfaz de Profiler.

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

Ve a Profiler.

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

Argumentos de nombre y versión del servicio

Cuando carga el agente de Profiler, especifica un argumento service-name y un argumento service-version opcional para configurarlo.

El nombre del servicio permite a Profiler recoger datos de perfil de todas las réplicas de ese servicio. El servicio de creación de perfiles asegura una frecuencia de recogida de un perfil por minuto, de media, para cada nombre de servicio en cada combinación de versiones y zonas de servicio.

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

Si usas nombres de servicio diferentes para tus réplicas, tu servicio se perfilará con más frecuencia de la necesaria, con una sobrecarga correspondientemente mayor.

Al seleccionar un nombre de servicio, ten en cuenta lo siguiente:

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

  • No utilices ningún valor específico del proceso, como un ID de proceso, en la cadena service-name.

  • La cadena service-name debe coincidir con esta expresión regular:

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

Una buena práctica es usar una cadena 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 perfil de varias instancias y mostrarla correctamente. Se puede usar para marcar diferentes versiones de tus servicios a medida que se implementan. La interfaz de usuario de Profiler te permite filtrar los datos por versión del servicio. De esta forma, puedes comparar el rendimiento de versiones anteriores y más recientes del código.

El valor del argumento service-version es una cadena de formato libre, pero los valores de este argumento suelen ser números de versión, como 1.0.0 o 2.1.2.

Registro de agentes

De forma predeterminada, el agente de creación de perfiles registra mensajes con un nivel de gravedad de error. Para configurar el agente de forma que registre mensajes con niveles de gravedad inferiores, especifica el parámetro verbose al iniciar el agente. Los valores admitidos para verbose son estos cuatro:

  • 0 : error
  • 1 : Advertencia
  • 2 : informativo
  • 3 : depuración

Si asignas el valor 1 al parámetro verbose en tu llamada a start, se registrarán los mensajes con un nivel de gravedad de Warning o Error, mientras que se ignorarán los mensajes Informational y Debug.

Para registrar todos los mensajes, asigna el valor 3 a verbose al iniciar el agente:

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

Solución de problemas

En esta sección se enumeran las limitaciones, las excepciones y los problemas conocidos específicos de la creación de perfiles de aplicaciones Python. Consulta la sección Solución de problemas para obtener ayuda con problemas habituales.

Limitaciones

Tipo de perfil Restricciones y limitaciones
Tiempo real
  • Solo se perfila el hilo principal.
  • La función de perfil start debe llamarse desde el hilo principal.
  • El controlador de señales del generador de perfiles solo se ejecuta en el hilo principal. Si el hilo principal no se puede ejecutar, no se capturan datos de perfil.

Excepciones

Error Causa Solución
NotImplementedError lanzados durante start La aplicación se ha ejecutado en un entorno que no es Linux.
  • Ejecuta tu aplicación en un entorno Linux.
ValueError lanzados durante start Los argumentos de la función start no son válidos, no se puede determinar la información necesaria a partir de las variables de entorno y los argumentos, o la creación de perfiles si se han inhabilitado tanto la creación de perfiles de tiempo de CPU como la de tiempo real.
  • Asegúrate de que el nombre y la versión del servicio cumplan los requisitos definidos en Argumentos de nombre y versión del servicio.
  • Si la creación de perfiles de pared está habilitada, asegúrate de que se llame a start desde el hilo principal.
  • Asegúrate de que estás usando una versión compatible de Python y de que el perfil de tiempo de CPU o de tiempo real está habilitado. Para obtener más información, consulta la función start.
  • Comprueba que has especificado el parámetro project_id como start si se ejecuta fuera de Google Cloud. Para obtener más información, consulta la función start.

Problemas conocidos

Comportamiento Causa Solución
No tienes datos de perfil o has habilitado un nuevo tipo de perfil y te faltan datos de perfil. Las causas habituales están relacionadas con la configuración. Consulta la sección Solución de problemas.
Estás usando uWSGI y no tienes datos de tiempo de CPU ni de perfil de tiempo real de todos los procesos.

Cuando uWSGI usa varios procesos de trabajo para gestionar solicitudes, el comportamiento predeterminado es inicializar la aplicación solo en el proceso principal ("master"). 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 Django, el agente de creación de perfiles no se configurará para los procesos bifurcados.

Para inicializar la aplicación en todos los procesos de trabajador, define 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 Wall, pero sí tienes datos de perfil de tiempo de CPU.

El generador de perfiles de Wall depende del módulo de señales de Python. Cuando el intérprete de Python se compila con compatibilidad con subprocesos, la configuración predeterminada inhabilita la gestión de señales personalizadas para los procesos bifurcados.

En el caso de las aplicaciones uWSGI, habilita la gestión de señales personalizadas definiendo 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 nuevas entradas:

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

Incidencia de GitHub

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

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

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

Si tu aplicación no puede ejecutarse de forma segura cuando se pierden las señales, te recomendamos que dejes de usar Cloud Profiler. Si se sigue usando, es posible que se pierdan números de señal y que haya demasiadas entradas en el registro de errores.

Ejecutar con Linux Alpine

El agente de creación de perfiles de Python para Linux Alpine solo se admite en 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 de dos fases y compilar el agente de creación de perfiles de Python en la primera fase. Por ejemplo, la siguiente imagen de Docker usa una compilación de varias fases 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 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 del agente.

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

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

Después, debes volver a compilar y desplegar la aplicación.

Siguientes pasos