Implementar webhooks

Este guia fornece vários exemplos para implementar webhooks, além de recomendações para solução de problemas de webhook.

Definir um parâmetro de sessão

Os exemplos a seguir mostram como definir um parâmetro de sessão.

Go

Para autenticar na Dialogflow CX, configure o Application Default Credentials. Para mais informações, consulte Configurar a autenticação para um ambiente de desenvolvimento local.

Consulte o Guia de início rápido de webhooks.

Java

Para autenticar na Dialogflow CX, configure o Application Default Credentials. Para mais informações, consulte Configurar a autenticação para um ambiente de desenvolvimento local.


// 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

Para autenticar na Dialogflow CX, configure o Application Default Credentials. Para mais informações, consulte Configurar a autenticação para um ambiente de desenvolvimento local.

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

Para autenticar na Dialogflow CX, configure o Application Default Credentials. Para mais informações, consulte Configurar a autenticação para um ambiente de desenvolvimento local.

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

Retornar uma resposta de fulfillment

Os exemplos a seguir mostram como retornar uma resposta de fulfillment.

Go

Para autenticar na Dialogflow CX, configure o Application Default Credentials. Para mais informações, consulte Configurar a autenticação para um ambiente de desenvolvimento local.

Consulte o Guia de início rápido de webhooks.

Java

Para autenticar na Dialogflow CX, configure o Application Default Credentials. Para mais informações, consulte Configurar a autenticação para um ambiente de desenvolvimento local.


// 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

Para autenticar na Dialogflow CX, configure o Application Default Credentials. Para mais informações, consulte Configurar a autenticação para um ambiente de desenvolvimento local.

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

Para autenticar na Dialogflow CX, configure o Application Default Credentials. Para mais informações, consulte Configurar a autenticação para um ambiente de desenvolvimento local.

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

Defina os parâmetros de formulário conforme necessário

Os exemplos a seguir mostram como sinalizar um parâmetro como obrigatório.

Java

Para autenticar na Dialogflow CX, configure o Application Default Credentials. Para mais informações, consulte Configurar a autenticação para um ambiente de desenvolvimento local.


// 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

Para autenticar na Dialogflow CX, configure o Application Default Credentials. Para mais informações, consulte Configurar a autenticação para um ambiente de desenvolvimento local.

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);
});

Validar um parâmetro de formulário

Os exemplos a seguir mostram como validar um parâmetro de formulário.

Java

Para autenticar na Dialogflow CX, configure o Application Default Credentials. Para mais informações, consulte Configurar a autenticação para um ambiente de desenvolvimento local.


// 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

Para autenticar na Dialogflow CX, configure o Application Default Credentials. Para mais informações, consulte Configurar a autenticação para um ambiente de desenvolvimento local.

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

Para autenticar na Dialogflow CX, configure o Application Default Credentials. Para mais informações, consulte Configurar a autenticação para um ambiente de desenvolvimento local.

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 da sessão de registro

O exemplo a seguir mostra como registrar o session ID de uma solicitação de webhook.

Python

Para autenticar na Dialogflow CX, configure o Application Default Credentials. Para mais informações, consulte Configurar a autenticação para um ambiente de desenvolvimento local.


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

Solução de problemas

Ciclo de uma chamada de webhook

As chamadas de webhook são sempre iniciadas pelo Dialogflow CX e vão para um servidor da Web por HTTPS. As chamadas de webhooks de serviços da Web genéricos são originadas de um endereço IP da Internet que pertence ao Google e podem alcançar servidores da Web (servidores de webhook) disponíveis na Internet pública. Por outro lado, os webhooks do Diretório de Serviços sempre começam em um endereço interno Google Cloud e só podem alcançar servidores de webhook em redes privadas dentro de Google Cloud.

Registros úteis para depurar webhooks

A depuração de problemas de webhook geralmente envolve a coleta dos registros do Cloud Logging do Dialogflow CX e dos registros do servidor de webhook. Se o servidor de webhook for implementado usando as funções do Cloud Run, os registros dele estarão no Cloud Logging. Caso contrário, os registros normalmente residiriam onde o servidor de webhook é executado.

Os registros de webhook padrão contêm um campo detectIntentResponseId com um UUID que pode ser útil para rastrear uma chamada específica em servidores de webhook. Esse registro existe nos registros do Cloud Logging do Dialogflow CX quando a geração de registros do Cloud está ativada.

Problemas comuns com webhooks

Alguns erros que podem ser encontrados nos registros do Dialogflow CX para chamadas de webhooks são:

Erro de resolução do nome do host do servidor de webhook

O Dialogflow CX procurou o nome do host de um webhook genérico, mas ele não existe no DNS. Verifique se o nome do host está registrado no DNS público. Se o nome do host for novo, pode levar algum tempo para que o registro seja propagado. Mensagem de registro do Cloud Logging: State: URL_ERROR, Reason: ERROR_DNS.

O servidor de webhook retorna um erro do lado do cliente

Além de ERROR_DNS, esse estado indica uma resposta 4xx do servidor de webhook. Isso pode ser um status não autorizado (401 - ERROR_AUTHENTICATION) ou que o URL não foi encontrado no servidor de webhook (404 - ERROR_NOT_FOUND). Mensagem de registro do Cloud Logging: State: URL_ERROR.

O agente do Dialogflow expira antes que o servidor de webhook retorne uma resposta

O Dialogflow CX atingiu o limite de tempo limite do webhook antes que o servidor da Web terminasse. As duas abordagens possíveis aqui são reduzir o tempo de processamento do servidor de webhook ou aumentar o tempo que o Dialogflow CX espera pelo webhook. Reduzir o tempo de processamento geralmente traz os melhores resultados, embora não seja trivial em muitos casos. Considere que há um limite máximo de tempo limite para webhooks e que os autores de chamadas ou usuários finais precisariam esperar mais para receber uma resposta do agente antes de aumentar essa configuração. Mensagem do Cloud Logging: State: URL_TIMEOUT, Reason: TIMEOUT_WEB.

O gRPC expira antes que o servidor de webhook retorne uma resposta.

O limite de tempo definido pelo gRPC na chamada de API do Dialogflow CX foi atingido antes que a chamada do webhook fosse concluída. Esse limite geralmente é definido no nível de integração e é independente dos parâmetros do Dialogflow CX e dos limites de tempo limite do webhook. Para mais informações sobre prazos do gRPC, consulte https://grpc.io/docs/guides/deadlines/. Mensagem do Cloud Logging: State: URL_REJECTED, Reason: REJECTED_DEADLINE_EXCEEDED.

O Dialogflow não conseguiu entrar em contato com o servidor de webhook

Não foi possível acessar o servidor de webhook devido a um erro de rede ou a conexão foi estabelecida e o servidor de webhook retornou o status HTTP 5xx, indicando um problema durante o processamento da solicitação. Verifique se o Dialogflow CX pode acessar o endereço do servidor de webhook no nível da rede. Se a solicitação aparecer nos registros do servidor de webhook, descubra por que a chamada retornou um erro 5xx. Mensagem de registro do Cloud Logging: State: URL_UNREACHABLE.

Como rastrear chamadas de webhook

Uma chamada de webhook padrão pode ser correlacionada entre o Dialogflow CX e um servidor de webhook usando o ID da sessão, o ID do detectIntentResponse, o ID de trace para funções do Cloud Run e um carimbo de data/hora da chamada. O rastreamento flexível de webhooks pode ser feito usando o carimbo de data/hora da chamada e os valores de parâmetro de sessão especificados na definição do webhook no momento do design. Para mais informações sobre solicitações de webhooks padrão e flexíveis, consulte Webhooks.

O ID da sessão aparece no campo sessionInfo.session da WebhookRequest. Esse ID de sessão precisa ser exclusivo para cada conversa e pode ajudar você a comparar os registros agênticos com os registros do webhook para solicitações que usam o mesmo ID de sessão. A seção anterior ID da sessão de registro mostra como registrar o ID da sessão de um webhook.

Além disso, se você estiver hospedando seu webhook no Cloud Run functions ou em uma opção sem servidor Google Cloud semelhante, poderá usar o campo trace das entradas de registro como um filtro de registro. Uma única execução de uma função resulta em várias entradas de registro com o mesmo valor de trace.

O próximo exemplo usa o ID da sessão e o valor do trace para associar um registro de erro específico do agente de CX do Dialogflow CX às entradas de registro do webhook do Cloud Run Functions correspondentes. O exemplo usa filtros do Cloud Logging para um agente que ativou o Cloud Logging.

1. Filtrar os registros de erro de um agente específico do Dialogflow CX

Use o seguinte filtro do Cloud Logging para filtrar os registros do Dialogflow CX em busca de registros de erro de um agente específico:

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

Uma entrada de erro de registro de webhook é semelhante a esta:

{
  "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"
}

Observe o campo labels.session_id, que contém o ID da sessão. Você vai usar o ID da sessão na próxima etapa.

2. Filtrar registros de funções do Cloud Run por ID da sessão

Use o seguinte filtro do Cloud Logging para filtrar os registros das funções do Cloud Run por ID de sessão:

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"

Os registros resultantes correspondem aos registros de webhook feitos durante a sessão fornecida. Exemplo:

{
  "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"
}

Anote o campo trace, que será usado na próxima etapa.

3. Filtrar registros de funções do Cloud para um trace específico

Use o seguinte filtro do Cloud Logging para filtrar os registros do função do Cloud de um determinado trace:

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"

em que TRACE_ID é o último segmento do trace. Por exemplo, o TRACE_ID para projects/PROJECT_ID/traces/e41eefc1fac48665b442bfa400cc2f5e é e41eefc1fac48665b442bfa400cc2f5e.

O resultado é o registro do servidor de webhook gerado durante a execução da solicitação de webhook associada ao ID da sessão da etapa 1 e ao trace da etapa 2. O registro será semelhante ao seguinte.

{
  "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
}