Implementare gli webhook

Questa guida fornisce vari esempi per l'implementazione dei webhook e consigli per la risoluzione dei problemi relativi ai webhook.

Impostare un parametro sessione

Gli esempi riportati di seguito mostrano come impostare un parametro di sessione.

Go

Per eseguire l'autenticazione in Dialogflow, configura le Credenziali predefinite dell'applicazione. Per ulteriori informazioni, consulta Configura l'autenticazione per un ambiente di sviluppo locale.

Consulta la guida rapida ai webhook.

Java

Per eseguire l'autenticazione in Dialogflow, configura le Credenziali predefinite dell'applicazione. Per ulteriori informazioni, consulta Configura l'autenticazione per un ambiente di sviluppo locale.


// TODO: Change class name to Example
// TODO: Uncomment the line below before running cloud function
// package com.example;

import com.google.cloud.functions.HttpFunction;
import com.google.cloud.functions.HttpRequest;
import com.google.cloud.functions.HttpResponse;
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import com.google.gson.JsonObject;
import java.io.BufferedWriter;

public class WebhookConfigureSessionParameters implements HttpFunction {
  @Override
  public void service(HttpRequest request, HttpResponse response) throws Exception {
    JsonObject orderParameter = new JsonObject();
    orderParameter.addProperty("order_number", "12345");

    JsonObject parameterObject = new JsonObject();
    parameterObject.add("parameters", orderParameter);

    // Creates webhook response object
    JsonObject webhookResponse = new JsonObject();
    webhookResponse.add("session_info", parameterObject);

    Gson gson = new GsonBuilder().setPrettyPrinting().create();
    String jsonResponseObject = gson.toJson(webhookResponse);

    /** { "session_info": { "parameters": { "order_number": "12345" } } } */
    BufferedWriter writer = response.getWriter();
    // Sends the webhookResponseObject
    writer.write(jsonResponseObject.toString());
  }
}

Node.js

Per eseguire l'autenticazione in Dialogflow, configura le Credenziali predefinite dell'applicazione. Per ulteriori informazioni, consulta Configura l'autenticazione per un ambiente di sviluppo locale.

const functions = require('@google-cloud/functions-framework');

functions.http('configureSessionParams', (request, response) => {
  // Session parameter configured by the webhook
  const orderNumber = 123;

  const jsonResponse = {
    sessionInfo: {
      parameters: {
        orderNumber: orderNumber,
      },
    },
  };

  response.send(jsonResponse);
});

Python

Per eseguire l'autenticazione in Dialogflow, configura le Credenziali predefinite dell'applicazione. Per ulteriori informazioni, consulta Configura l'autenticazione per un ambiente di sviluppo locale.

import functions_framework

# TODO (developer): change entry point to configure_session_params in Cloud Function


@functions_framework.http
def configure_session_params(request):
    """Webhook to validate or configure new session parameters."""

    order_number = 123

    json_response = {
        "sessionInfo": {
            "parameters": {
                "orderNumber": order_number,
            },
        },
    }

    return json_response

Restituisci una risposta di evasione

Gli esempi riportati di seguito mostrano come restituire una risposta di evasione.

Go

Per eseguire l'autenticazione in Dialogflow, configura le Credenziali predefinite dell'applicazione. Per ulteriori informazioni, consulta Configura l'autenticazione per un ambiente di sviluppo locale.

Consulta la guida rapida ai webhook.

Java

Per eseguire l'autenticazione in Dialogflow, configura le Credenziali predefinite dell'applicazione. Per ulteriori informazioni, consulta Configura l'autenticazione per un ambiente di sviluppo locale.


// TODO: Change class name to Example
// TODO: add GSON dependency to Pom file
// (https://mvnrepository.com/artifact/com.google.code.gson/gson/2.8.5)
// TODO: Uncomment the line bellow before running cloud function
// package com.example;

import com.google.cloud.functions.HttpFunction;
import com.google.cloud.functions.HttpRequest;
import com.google.cloud.functions.HttpResponse;
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import com.google.gson.JsonObject;
import com.google.gson.JsonParser;
import java.io.BufferedWriter;

public class BasicWebhook implements HttpFunction {
  @Override
  public void service(HttpRequest request, HttpResponse response) throws Exception {
    Gson gson = new GsonBuilder().create();
    JsonObject parsedRequest = gson.fromJson(request.getReader(), JsonObject.class);

    // For more information on the structure of this object https://cloud.google.com/dialogflow/cx/docs/reference/rest/v3/Fulfillment
    String requestTag = parsedRequest.getAsJsonObject("fulfillmentInfo")
        .getAsJsonPrimitive("tag").toString();
    JsonObject responseObject = null;
    String defaultIntent = "\"Default Welcome Intent\"";
    String secondIntent = "\"get-agent-name\"";
    String responseText = "";

    // Compares the Intent Tag to provide the correct response 
    if (requestTag.equals(defaultIntent)) {
      responseText = "\"Hello from a Java GCF Webhook\"";
    } else if (requestTag.equals(secondIntent)) {
      responseText = "\"My name is Flowhook\"";
    } else {
      responseText = "\"Sorry I didn't get that\"";
    }

    // Constructing the response jsonObject 
    responseObject =
        JsonParser
            .parseString(
                "{ \"fulfillment_response\": { \"messages\": [ { \"text\": { \"text\": ["
                    + responseText
                    + "] } } ] } }")
            .getAsJsonObject();
    BufferedWriter writer = response.getWriter();

    //Sends the responseObject
    writer.write(responseObject.toString());
  }
}

Node.js

Per eseguire l'autenticazione in Dialogflow, configura le Credenziali predefinite dell'applicazione. Per ulteriori informazioni, consulta Configura l'autenticazione per un ambiente di sviluppo locale.

const functions = require('@google-cloud/functions-framework');

functions.http('handleWebhook', (request, response) => {
  const tag = request.body.fulfillmentInfo.tag;
  let text = '';

  if (tag === 'Default Welcome Intent') {
    text = 'Hello from a GCF Webhook';
  } else if (tag === 'get-name') {
    text = 'My name is Flowhook';
  } else {
    text = `There are no fulfillment responses defined for "${tag}"" tag`;
  }

  const jsonResponse = {
    fulfillment_response: {
      messages: [
        {
          text: {
            //fulfillment text response to be sent to the agent
            text: [text],
          },
        },
      ],
    },
  };

  response.send(jsonResponse);
});

Python

Per eseguire l'autenticazione in Dialogflow, configura le Credenziali predefinite dell'applicazione. Per ulteriori informazioni, consulta Configura l'autenticazione per un ambiente di sviluppo locale.

import functions_framework

# TODO(developer): change entry point to handle_webhook in cloud function


@functions_framework.http
def handle_webhook(request):
    req = request.get_json()

    tag = req["fulfillmentInfo"]["tag"]

    if tag == "Default Welcome Intent":
        text = "Hello from a GCF Webhook"
    elif tag == "get-name":
        text = "My name is Flowhook"
    else:
        text = f"There are no fulfillment responses defined for {tag} tag"

    # You can also use the google.cloud.dialogflowcx_v3.types.WebhookRequest protos instead of manually writing the json object
    # Please see https://googleapis.dev/python/dialogflow/latest/dialogflow_v2/types.html?highlight=webhookresponse#google.cloud.dialogflow_v2.types.WebhookResponse for an overview
    res = {"fulfillment_response": {"messages": [{"text": {"text": [text]}}]}}

    # Returns json
    return res

Imposta i parametri del modulo in base alle esigenze.

Gli esempi riportati di seguito mostrano come contrassegnare un parametro come obbligatorio.

Java

Per eseguire l'autenticazione in Dialogflow, configura le Credenziali predefinite dell'applicazione. Per ulteriori informazioni, consulta Configura l'autenticazione per un ambiente di sviluppo locale.


// TODO: Change class name to Example
// TODO: Uncomment the line below before running cloud function
// package com.example;

import com.google.cloud.functions.HttpFunction;
import com.google.cloud.functions.HttpRequest;
import com.google.cloud.functions.HttpResponse;
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import com.google.gson.JsonArray;
import com.google.gson.JsonObject;
import java.io.BufferedWriter;

public class ConfigureWebhookToSetFormParametersAsOptionalOrRequired implements HttpFunction {
  @Override
  public void service(HttpRequest request, HttpResponse response) throws Exception {
    JsonObject parameterObject = new JsonObject();
    parameterObject.addProperty("display_name", "order_number");
    parameterObject.addProperty("required", "true");
    parameterObject.addProperty("state", "VALID");

    JsonArray parameterInfoList = new JsonArray();
    parameterInfoList.add(parameterObject);

    JsonObject parameterInfoObject = new JsonObject();
    parameterInfoObject.add("parameter_info", parameterInfoList);

    JsonObject formInfo = new JsonObject();
    formInfo.add("form_info", parameterInfoObject);

    // Constructs the webhook response object
    JsonObject webhookResponse = new JsonObject();
    webhookResponse.add("page_info", formInfo);

    Gson gson = new GsonBuilder().setPrettyPrinting().create();
    String jsonResponseObject = gson.toJson(webhookResponse);

    /* {
     *   "page_info": {
     *     "form_info": {
     *       "parameter_info": [
     *         {
     *           "display_name": "order_number",
     *           "required": "true",
     *           "state": "VALID"
     *         }
     *       ]
     *     }
     *   }
     * }
     */

    BufferedWriter writer = response.getWriter();

    // Sends the responseObject
    writer.write(jsonResponseObject.toString());
  }
}

Node.js

Per eseguire l'autenticazione in Dialogflow, configura le Credenziali predefinite dell'applicazione. Per ulteriori informazioni, consulta Configura l'autenticazione per un ambiente di sviluppo locale.

const functions = require('@google-cloud/functions-framework');

functions.http('configureOptionalFormParam', (request, response) => {
  // The value of the parameter that the webhook will set as optional or required.
  // Note that the webhook cannot add or remove any form parameter

  const jsonResponse = {
    pageInfo: {
      formInfo: {
        parameterInfo: [
          {
            displayName: 'order-number',
            // if required: false, the agent will not reprompt for this parameter, even if the state is 'INVALID'
            required: true,
            state: 'VALID',
          },
        ],
      },
    },
  };

  // Info about form parameter that is sent in the webhook response:
  console.log(
    'Parameter Info: \n',
    jsonResponse.pageInfo.formInfo.parameterInfo[0]
  );

  response.send(jsonResponse);
});

Convalidare un parametro del modulo

Gli esempi riportati di seguito mostrano come convalidare un parametro del modulo.

Java

Per eseguire l'autenticazione in Dialogflow, configura le Credenziali predefinite dell'applicazione. Per ulteriori informazioni, consulta Configura l'autenticazione per un ambiente di sviluppo locale.


// TODO: Change class name to Example
// TODO: Uncomment the line below before running cloud function
// package com.example;

import com.google.cloud.functions.HttpFunction;
import com.google.cloud.functions.HttpRequest;
import com.google.cloud.functions.HttpResponse;
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import com.google.gson.JsonArray;
import com.google.gson.JsonObject;
import java.io.BufferedWriter;

public class WebhookValidateFormParameter implements HttpFunction {
  @Override
  public void service(HttpRequest request, HttpResponse response) throws Exception {
    JsonObject sessionInfo = new JsonObject();
    JsonObject sessionParameter = new JsonObject();

    sessionParameter.addProperty("order_number", "null");
    sessionInfo.add("parameters", sessionParameter);

    JsonObject parameterObject = new JsonObject();
    parameterObject.addProperty("display_name", "order_number");
    parameterObject.addProperty("required", "true");
    parameterObject.addProperty("state", "INVALID");
    parameterObject.addProperty("value", "123");

    JsonArray parameterInfoList = new JsonArray();
    parameterInfoList.add(parameterObject);

    JsonObject parameterInfoObject = new JsonObject();
    parameterInfoObject.add("parameter_info", parameterInfoList);

    JsonObject pageInfo = new JsonObject();
    pageInfo.add("form_info", parameterInfoObject);

    // Constructs the webhook response object
    JsonObject webhookResponse = new JsonObject();
    webhookResponse.add("page_info", pageInfo);
    webhookResponse.add("session_info", sessionInfo);

    Gson gson = new GsonBuilder().setPrettyPrinting().create();
    String jsonResponseObject = gson.toJson(webhookResponse);

    /**
     * { "page_info": { "form_info": { "parameter_info": [ { "display_name": "order_number",
     * "required": "true", "state": "INVALID", "value": "123" } ] } }, "session_info": {
     * "parameters": { "order_number": "null" } } }
     */
    BufferedWriter writer = response.getWriter();

    // Sends the responseObject
    writer.write(jsonResponseObject.toString());
  }
}

Node.js

Per eseguire l'autenticazione in Dialogflow, configura le Credenziali predefinite dell'applicazione. Per ulteriori informazioni, consulta Configura l'autenticazione per un ambiente di sviluppo locale.

const functions = require('@google-cloud/functions-framework');

functions.http('validateParameter', (request, response) => {
  // Webhook will validate or invalidate parameter based on logic configured by the user.
  // Access parameter values through the webhook request via `request.body.pageInfo.formInfo.parameterInfo[]`
  const jsonResponse = {
    page_info: {
      form_info: {
        parameter_info: [
          {
            displayName: 'orderNumber',
            required: true,
            state: 'INVALID',
            value: 123,
          },
        ],
      },
    },
    sessionInfo: {
      parameters: {
        // Set session parameter to null if the form parameter is 'INVALID' and your agent needs to reprompt the user
        orderNumber: null,
      },
    },
  };

  response.send(jsonResponse);
});

Python

Per eseguire l'autenticazione in Dialogflow, configura le Credenziali predefinite dell'applicazione. Per ulteriori informazioni, consulta Configura l'autenticazione per un ambiente di sviluppo locale.

import functions_framework


@functions_framework.http
def validate_parameter(request):
    """Webhook will validate or invalidate parameter based on logic configured by the user."""
    return {
        "page_info": {
            "form_info": {
                "parameter_info": [
                    {
                        "displayName": "orderNumber",
                        "required": True,
                        "state": "INVALID",
                        "value": 123,
                    },
                ],
            },
        },
        "sessionInfo": {
            "parameters": {
                # Set session parameter to None if the form parameter is 'INVALID' and your agent needs to reprompt the user
                "orderNumber": None,
            },
        },
    }

ID sessione log

Il seguente esempio mostra come registrare session ID da una richiesta webhook.

Python

Per eseguire l'autenticazione in Dialogflow, configura le Credenziali predefinite dell'applicazione. Per ulteriori informazioni, consulta Configura l'autenticazione per un ambiente di sviluppo locale.


import re

import functions_framework


@functions_framework.http
def log_session_id_for_troubleshooting(request):
    """Webhook will log session id corresponding to request."""

    req = request.get_json()
    # You can read more about SessionInfo at https://cloud.google.com/dialogflow/cx/docs/reference/rest/v3/SessionInfo
    # Use a regex pattern to get the session ID
    session_id_regex = r".+\/sessions\/(.+)"
    session = req["sessionInfo"]["session"]
    regex_match = re.search(session_id_regex, session)
    session_id = regex_match.group(1)

    # Instead of printing, use the logging tools available to you
    print(f"Debug Node: session ID = {session_id}")

    # Return a generic response
    res = {
        "fulfillment_response": {
            "messages": [{"text": {"text": [f"Request Session ID: {session_id}"]}}]
        }
    }

    # Returns json
    return res

Risoluzione dei problemi

Durata di una chiamata webhook

Le chiamate webhook vengono sempre avviate da Conversational Agents (Dialogflow CX) e vanno a un server web tramite HTTPS. Le chiamate webhook del servizio web generico hanno origine da un indirizzo IP internet di proprietà di Google e possono raggiungere server web (server webhook) disponibili su internet pubblico. D'altra parte, i webhook di Service Directory iniziano sempre da un indirizzoGoogle Cloud interno e possono raggiungere solo i server webhook nelle reti private all'interno di Google Cloud.

Log utili per il debug dei webhook

Il debug dei problemi relativi ai webhook in genere comporta la raccolta dei log di Cloud Logging di Dialogflow e dei log del server webhook. Se il server webhook è implementato utilizzando le funzioni Cloud Run, i relativi log si troveranno in Cloud Logging. In caso contrario, i log si trovano in genere nella posizione in cui viene eseguito il server webhook.

I log webhook standard contengono un campo detectIntentResponseId con un UUID che può essere utile per tracciare una chiamata specifica nei server webhook. Questo log esiste nei log di Cloud Logging di Dialogflow quando Cloud Logging è abilitato.

Problemi comuni relativi ai webhook

Alcuni errori che possono essere trovati nei log di Dialogflow per le chiamate webhook sono:

Errore di risoluzione del nome host del server webhook

Dialogflow ha cercato il nome host di un webhook generico e il nome host non esiste nel DNS. Assicurati che il nome host sia registrato nel DNS pubblico. Se il nome host è nuovo, la propagazione del record potrebbe richiedere del tempo. Messaggio di Cloud Logging: State: URL_ERROR, Reason: ERROR_DNS.

Il server webhook restituisce un errore lato client

A parte ERROR_DNS, questo stato indica una risposta 4xx dal server webhook. Può trattarsi di uno stato non autorizzato (401 - ERROR_AUTHENTICATION) o che l'URL non è stato trovato nel server webhook (404 - ERROR_NOT_FOUND). Messaggio di Cloud Logging: State: URL_ERROR.

Timeout dell'agente Dialogflow prima che il server webhook restituisca una risposta

Dialogflow ha raggiunto il limite di timeout del webhook prima che il server web terminasse. I due approcci possibili sono ridurre il tempo di elaborazione del server webhook o aumentare il tempo di attesa del webhook da parte di Dialogflow. La riduzione del tempo di elaborazione di solito porta a risultati migliori, anche se in molti casi non è semplice. Tieni presente che esiste un limite di timeout massimo per i webhook e che i chiamanti o gli utenti finali dovranno attendere più a lungo per ricevere una risposta dall'agente prima di aumentare questa impostazione. Cloud Logging message: State: URL_TIMEOUT, Reason: TIMEOUT_WEB.

gRPC va in timeout prima che il server webhook restituisca una risposta

Il limite di tempo impostato da gRPC nella chiamata API Dialogflow è stato raggiunto prima del termine della chiamata webhook. Questo limite viene impostato di solito a livello di integrazione ed è indipendente dai parametri Dialogflow e dai limiti di timeout dei webhook. Per ulteriori informazioni sulle scadenze gRPC, visita la pagina https://grpc.io/docs/guides/deadlines/. Cloud Logging message: State: URL_REJECTED, Reason: REJECTED_DEADLINE_EXCEEDED.

Dialogflow non è riuscito a contattare il server webhook

Non è stato possibile raggiungere il server webhook a causa di un errore di rete o la connessione è stata stabilita e il server webhook ha restituito lo stato HTTP 5xx, che indica un problema durante l'elaborazione della richiesta. Assicurati che Dialogflow possa raggiungere l'indirizzo del server webhook a livello di rete. Se la richiesta viene visualizzata nei log del server webhook, scopri perché la chiamata ha restituito un errore 5xx. Messaggio di Cloud Logging: State: URL_UNREACHABLE.

Tracciamento delle chiamate webhook

Una chiamata webhook standard può essere correlata tra Dialogflow e un server webhook utilizzando l'ID sessione, l'ID detectIntentResponse, l'ID traccia per le funzioni Cloud Run e un timestamp della chiamata. Il tracciamento flessibile dei webhook può essere eseguito utilizzando il timestamp della chiamata e i valori dei parametri di sessione specificati nella definizione del webhook in fase di progettazione. Per ulteriori informazioni sulle richieste webhook standard e flessibili, consulta Webhook.

L'ID sessione viene visualizzato nel campo sessionInfo.session di WebhookRequest. Questo ID sessione deve essere univoco per ogni conversazione e può aiutarti a confrontare i log degli agenti con i log dei webhook per le richieste che utilizzano lo stesso ID sessione. La sezione precedente ID sessione log mostra come registrare l'ID sessione da un webhook.

Inoltre, se ospiti il webhook su Cloud Run Functions o su un'opzione serverless Google Cloud simile, puoi utilizzare il campo trace delle voci di log come filtro dei log. Una singola esecuzione di una funzione genera più voci di log con lo stesso valore di traccia.

L'esempio successivo utilizza sia l'ID sessione sia il valore di traccia per associare un log di errori di un agente Dialogflow specifico alle voci di log del webhook delle funzioni Cloud Run corrispondenti. L'esempio utilizza filtri di Cloud Logging per un agente che ha abilitato Cloud Logging.

1. Filtrare i log di Dialogflow per i log degli errori di un agente specifico

Utilizza il seguente filtro Cloud Logging per filtrare i log di Dialogflow in base ai log degli errori di un agente specifico:

labels.location_id="global"
labels.agent_id="AGENT_ID"
severity=ERROR

Una voce di errore del log webhook è simile alla seguente:

{
  "insertId": "-j4gkkre31e2o",
  "jsonPayload": {
    "code": 14,
    "message": "Error calling webhook 'https://us-central1-PROJECT_ID.cloudfunctions.net/function-webhook': State: URL_UNREACHABLE, Reason: UNREACHABLE_5xx, HTTP status code: 500"
  },
  "labels": {
    "agent_id": "e9e01392-1351-42dc-9b15-b583fb2d2881",
    "environment_id": "",
    "location_id": "global",
    "session_id": "07c899-a86-78b-a77-569625b37"
  },
  "logName": "projects/PROJECT_ID/logs/dialogflow-runtime.googleapis.com%2Frequests",
  "receiveTimestamp": "2024-10-28T21:49:04.288439054Z",
  "resource": {
    "labels": {
      "project_id": "PROJECT_ID"
    },
    "type": "global",
  },
  "severity": "ERROR",
  "timestamp": "2024-10-28T21:49:04.132548Z"
}

Prendi nota del campo labels.session_id che contiene l'ID sessione. Utilizzerai l'ID sessione nel passaggio successivo.

2. Filtrare i log delle funzioni Cloud Run per ID sessione

Utilizza il seguente filtro Cloud Logging per filtrare i log delle funzioni Cloud Run in base all'ID sessione:

resource.type = "cloud_run_revision"
resource.labels.service_name = "CLOUD_RUN_FUNCTION_NAME"
resource.labels.location = "CLOUD_RUN_FUNCTION_REGION"
textPayload="Debug Node: session ID = SESSION_ID"

I log risultanti corrispondono ai log webhook creati durante la sessione fornita. Ad esempio:

{
  "insertId": "671c42940007ebebdbb1d56e",
  "labels": {
    "execution_id": "pgy8jvvblovs",
    "goog-managed-by": "cloudfunctions",
    "instance_id": "004940b3b8e3d975a4b11a4ed7d1ded4ce3ed37467ffc5e2a8f13a1908db928f8200b01cc554a5eda66ffc9d23d76dd75cec1619a07cb5751fa2e8a93bc6cfc3df86dfa0650a"
  },
  "logName": "projects/PROJECT_ID/logs/run.googleapis.com%2Fstdout",
  "receiveTimestamp": "2024-10-26T01:15:00.523313187Z",
  "resource": {
    "labels": {
      "configuration_name": "function-webhook",
      "location": "us-central1",
      "project_id": "PROJECT_ID",
      "revision_name": "function-webhook-00001-jiv",
      "service_name": "function-webhook",
    },
    "type": "cloud_run_revision"
  },
  "spanId": "6938366936362981595",
  "trace": "d1b54fbc8945dd59bdcaed37d7d5e185",
  "textPayload": "Debug Node: session ID = 07c899-a86-78b-a77-569625b37",
  "timestamp": "2024-10-26T01:15:00.519147Z"
}

Prendi nota del campo trace, che viene utilizzato nel passaggio successivo.

3. Filtrare i log di Cloud Functions per una traccia specifica

Utilizza il seguente filtro Cloud Logging per filtrare i log diCloud Functions per una traccia specifica:

resource.type = "cloud_run_revision"
resource.labels.service_name = "CLOUD_RUN_FUNCTION_NAME"
resource.labels.location = "CLOUD_RUN_FUNCTION_REGION"
trace="projects/PROJECT_ID/traces/TRACE_ID"

dove TRACE_ID è l'ultimo segmento della traccia. Ad esempio, il TRACE_ID per projects/PROJECT_ID/traces/e41eefc1fac48665b442bfa400cc2f5e è e41eefc1fac48665b442bfa400cc2f5e.

Il risultato è il log del server webhook generato durante l'esecuzione della richiesta webhook associata all'ID sessione del passaggio 1 e alla traccia del passaggio 2. Il log sarà simile al seguente.

{
  "insertId": "671c42940008465e29f5faf0",
  "httpRequest": {
    "requestMethod": "POST",
    "requestUrl": "https://us-central1-TEST_PROJECT.cloudfunctions.net/function-webhook",
    "requestSize": "2410",
    "status": 200,
    "responseSize": "263",
    "userAgent": "Google-Dialogflow",
    "remoteIp": "8.34.210.1",
    "serverIp": "216.239.36.1",
    "latency": "0.166482342s",
    "protocol": "HTTP/1.1"
  },
  "resource": {
    "type": "cloud_run_revision",
    "labels": {
      "project_id": "PROJECT_ID",
      "service_name": "function-webhook",
      "location": "us-central1",
      "revision_name": "function-webhook-00001-jiv",
      "configuration_name": "function-webhook"
    }
  },
  "timestamp": "2024-10-26T01:15:00.352197Z",
  "severity": "INFO",
  "labels": {
    "instanceId": "004940b3b813af8a656c92aac1bd07ffad5165f1353e1e346b6161c14bcde225f68f4a88ceedc08aa9020f387b1b59471f73de45f2882a710ced37dea921f05ad962347690be",
    "goog-managed-by": "cloudfunctions"
  },
  "logName": "projects/test-project-12837/logs/run.googleapis.com%2Frequests",
  "trace": "projects/test-project-12837/traces/d1b54fbc8945dd59bdcaed37d7d5e185",
  "receiveTimestamp": "2024-10-26T01:15:00.548931586Z",
  "spanId": "604a07f7b33b18db",
  "traceSampled": true
}