Journaliser un agent

Pour utiliser Cloud Logging dans les agents lorsqu'ils sont déployés dans le runtime Vertex AI Agent Engine, utilisez l'une des méthodes suivantes :

  • stdout / stderr : par défaut (sans aucune configuration supplémentaire), les journaux écrits dans stdout et stderr sont respectivement redirigés vers les ID de journaux reasoning_engine_stdout et reasoning_engine_stderr. La seule limite est qu'ils doivent être au format texte.
  • Journalisation Python : le journaliseur Python intégré peut être intégré à Cloud Logging. Par rapport à l'écriture dans stdout ou stderr, cela prend en charge les journaux structurés et nécessite une configuration minimale.
  • Client Cloud Logging : les utilisateurs peuvent écrire des journaux structurés et contrôler entièrement le journaliseur (par exemple, en définissant le logName et le type de ressource).

Écrire des journaux pour un agent

Lorsque vous écrivez des journaux pour un agent, déterminez les éléments suivants :

  • severity : par exemple, "info", "warn", "error"
  • payload : contenu du journal (par exemple, texte ou JSON)
  • Champs supplémentaires : pour la mise en corrélation entre les journaux (par exemple, trace/span, tags, libellés)

Par exemple, pour enregistrer l'entrée de chaque requête lors du développement d'un agent :

stdout ou stderr

from typing import Dict

class MyAgent:

    def set_up(self):
        # No set up required. The logs from stdout and stderr are routed to
        # `reasoning_engine_stdout` and `reasoning_engine_stderr` respectively.
        pass

    def query(self, input: Dict):
        import sys

        print(
            f"input: {input}",
            file=sys.stdout,  # or sys.stderr
        )

Journalisation Python

from typing import Dict

class MyAgent:

    def set_up(self):
        import os
        import google.cloud.logging

        self.logging_client = google.cloud.logging.Client(project="PROJECT_ID")
        self.logging_client.setup_logging(
            name="LOG_ID",  # the ID of the logName in Cloud Logging.
            resource=google.cloud.logging.Resource(
                type="aiplatform.googleapis.com/ReasoningEngine",
                labels={
                    "location": "LOCATION",
                    "resource_container": "PROJECT_ID",
                    "reasoning_engine_id": os.environ.get("GOOGLE_CLOUD_AGENT_ENGINE_ID", ""),
                },
            ),
        )

    def query(self, input: Dict):
        import logging
        import json

        logging_extras = {
            "labels": {"foo": "bar"},
            "trace": "TRACE_ID",
        }

        logging.info( # or .warning(), .error()
            json.dumps(input),
            extra=logging_extras,
        )

Client Cloud Logging

from typing import Dict

class MyAgent:

    def set_up(self):
        import os
        import google.cloud.logging

        self.logging_client = google.cloud.logging.Client(project="PROJECT_ID")
        self.logger = self.logging_client.logger(
            name="LOG_ID",  # the ID of the logName in Cloud Logging.
            resource=google.cloud.logging.Resource(
                type="aiplatform.googleapis.com/ReasoningEngine",
                labels={
                    "location": "LOCATION",
                    "resource_container": "PROJECT_ID",
                    "reasoning_engine_id": os.environ.get("GOOGLE_CLOUD_AGENT_ENGINE_ID", ""),
                },
            ),
        )

    def query(self, input: Dict):
        logging_extras = {
            "labels": {"foo": "bar"},
            "trace": "TRACE_ID",
        }

        self.logger.log_struct(
            input,
            severity="INFO",  # or "DEBUG", "WARNING", "ERROR", "CRITICAL"
            **logging_extras,
        )

Lorsque l'agent est déployé et interrogé, il génère des entrées de journal. Par exemple, le code

remote_agent = agent_engines.create(
    MyAgent(),
    requirements=["cloudpickle==3", "google-cloud-logging"],
)

remote_agent.query(input={"hello": "world"})

génère une entrée de journal semblable à la suivante :

stdout ou stderr

{
  "insertId": "67a3bb3b000cc2df444361ab",
  "textPayload": "input: {'hello': 'world'}",
  "resource": {
    "type": "aiplatform.googleapis.com/ReasoningEngine",
    "labels": {
      "location": "LOCATION",
      "resource_container": "PROJECT_ID",
      "reasoning_engine_id": "RESOURCE_ID"
    }
  },
  "timestamp": "2025-02-05T19:25:47.836319Z",
  "logName": "projects/PROJECT_ID/logs/aiplatform.googleapis.com%2Freasoning_engine_stdout",  # or `*_stderr`
  "receiveTimestamp": "2025-02-05T19:25:47.842550772Z"
}

Journalisation Python

{
  "insertId": "1ek9a2jfqh777z",
  "jsonPayload": {"hello": "world"},
  "resource": {
    "type": "aiplatform.googleapis.com/ReasoningEngine",
    "labels": {
      "location": "LOCATION",
      "resource_container": "PROJECT_ID",
      "reasoning_engine_id": "RESOURCE_ID",
    }
  },
  "timestamp": "2025-02-05T20:30:19.348067Z",
  "severity": "INFO",
  "labels": {
    "foo": "bar",
    "python_logger": "root",
  },
  "logName": "projects/PROJECT_ID/logs/LOG_ID",
  "trace": "TRACE_ID",
  "receiveTimestamp": "2025-01-30T21:38:50.776813191Z"
}

Client Cloud Logging

{
  "insertId": "1ek9a2jfqh777z",
  "jsonPayload": {"hello": "world"},
  "resource": {
    "type": "aiplatform.googleapis.com/ReasoningEngine",
    "labels": {
      "location": "LOCATION",
      "resource_container": "PROJECT_ID",
      "reasoning_engine_id": "RESOURCE_ID",
    }
  },
  "timestamp": "2025-01-30T21:38:50.776813191Z",
  "severity": "INFO",
  "labels": {"foo": "bar"},
  "logName": "projects/PROJECT_ID/logs/LOG_ID",
  "trace": "TRACE_ID",
  "receiveTimestamp": "2025-01-30T21:38:50.776813191Z"
}

Afficher les journaux d'un agent

Vous pouvez afficher vos entrées de journal à l'aide de l'explorateur de journaux :

  1. Pour obtenir l'autorisation d'afficher les journaux dans l'explorateur de journaux, demandez à votre administrateur de vous accorder le rôle Lecteur de journaux (roles/logging.viewer) sur votre projet.

  2. Accédez à l'explorateur de journaux dans la console Google Cloud  :

    Accéder à l'explorateur de journaux

  3. En haut de la page, sélectionnez votre projet Google Cloud (correspondant à PROJECT_ID).

  4. Dans Type de ressource, sélectionnez Vertex AI Agent Builder Reasoning Engine.

Pour les agents basés sur l'Agent Development Kit, vous pouvez également afficher les journaux de votre agent dans la console Google Cloud à l'aide du tableau de bord Vertex AI Agent Engine.

Requêtes d'exécution

Vous pouvez filtrer les journaux dans Cloud Logging par opération compatible d'un agent déployé. Pour ce faire, filtrez les journaux en fonction du point de terminaison REST sous-jacent pour chaque requête d'opération :

  • POST /api/reasoning_engine : pour les requêtes adressées aux méthodes synchrones et asynchrones.
  • POST /api/stream_reasoning_engine : pour les requêtes adressées aux méthodes de streaming et de streaming asynchrone.
  • POST /api/bidi_reasoning_engine : pour les requêtes envoyées aux méthodes de streaming bidirectionnel.

Les requêtes d'exécution sont acheminées vers les points de terminaison REST en fonction du champ api_mode dans la liste des opérations compatibles d'un agent déployé.

Créer des requêtes

Vous pouvez utiliser l'explorateur de journaux pour créer des requêtes de manière incrémentielle. Les requêtes sont généralement créées en fonction des considérations suivantes :

  • timeline : pour rechercher des entrées de journal pertinentes en fonction de l'heure
  • scope : permet de rechercher des entrées de journal pertinentes en fonction d'attributs canoniques.
    • resource : séparez-le des autres types de ressources de votre projet.
      • type : s'affiche sous le nom "Vertex AI Agent Builder Reasoning Engine" dans l'explorateur de journaux et "aiplatform.googleapis.com/ReasoningEngine" dans l'entrée de journal.
      • labels : pour l'emplacement (LOCATION), le projet PROJECT_ID et la ressource RESOURCE_ID.
    • logName : journal auquel appartient l'entrée de journal :
      • Les entrées de journal au moment de la compilation ont l'ID de journal reasoning_engine_build.
      • Les entrées de journal pour stdout et stderr ont respectivement les ID de journal reasoning_engine_stdout et reasoning_engine_stderr.
      • Les entrées de journal de la journalisation Python ou du client Cloud Logging auront des ID de journal personnalisés en fonction de votre code dans Écrire des journaux pour un agent.
    • trace et span : pour les journaux lors de l'analyse des requêtes.
    • severity : gravité de l'entrée de journal.
    • insertId : identifiant unique d'une entrée de journal.
  • labels : carte de paires clé/valeur fournissant des informations supplémentaires sur l'entrée de journal. Les libellés peuvent être définis par l'utilisateur ou par le système. Ils sont utiles pour classer les journaux et faciliter leur recherche dans l'explorateur de journaux.
  • payload : contenu de l'entrée de journal.

Voici un exemple de requête pour tous les journaux INFO d'un agent déployé avec RESOURCE_ID :

resource.labels.reasoning_engine_id=RESOURCE_ID AND
severity=INFO

Vous pouvez l'afficher dans l'explorateur de journaux à l'adresse suivante :

https://https://console.cloud.google.com/logs/query;query=severity%3DINFO%0Aresource.labels.reasoning_engine_id%3D%22RESOURCE_ID%22;duration=DURATION?project=PROJECT_ID

où la requête a été correctement encodée au format URL et où les autres paramètres sont les suivants :

  • DURATION : par exemple, PT30M pour les 30 dernières minutes (ou PT10M pour les 10 dernières minutes) et
  • PROJECT_ID : projet Google Cloud .

Pour en savoir plus, consultez Créer et enregistrer des requêtes à l'aide du langage de requête Logging.

Interroger les journaux d'un agent

Pour une approche programmatique des journaux de requête, deux options courantes sont disponibles :

Python

from google.cloud import logging

logging_client = logging.Client(project="PROJECT_ID")
logger = logging_client.logger("LOG_ID")  # E.g. "logging_client"
print("Listing entries for logger {}:".format(logger.name))
for entry in logger.list_entries(
    filter_="resource.labels.reasoning_engine_id=RESOURCE_ID"  # Optional
):
    timestamp = entry.timestamp.isoformat()
    print("* {}: {}".format(timestamp, entry.payload))

Chaque entry correspondra à un LogEntry. Pour en savoir plus sur les arguments d'entrée de logger.list_entries, consultez la documentation de référence de l'API.

SQL

Vue des journaux :

SELECT *
FROM `PROJECT_ID.LOCATION.BUCKET_ID.LOG_VIEW_ID`

Vue Analytics :

SELECT *
FROM `analytics_view.PROJECT_ID.LOCATION.ANALYTICS_VIEW_ID`