Webhook を実装する

このガイドでは、Webhook を実装するためのさまざまなサンプルと、Webhook のトラブルシューティングに関する推奨事項について説明します。

セッション パラメータを設定する

以下のサンプルは、セッション パラメータを設定する方法を示しています。

Go

Dialogflow CX への認証を行うには、アプリケーションのデフォルト認証情報を設定します。 詳細については、 ローカル開発環境の認証の設定をご覧ください。

Webhook クイックスタートをご覧ください。

Java

Dialogflow CX への認証を行うには、アプリケーションのデフォルト認証情報を設定します。 詳細については、 ローカル開発環境の認証の設定をご覧ください。


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

Dialogflow CX への認証を行うには、アプリケーションのデフォルト認証情報を設定します。 詳細については、 ローカル開発環境の認証の設定をご覧ください。

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

Dialogflow CX への認証を行うには、アプリケーションのデフォルト認証情報を設定します。 詳細については、 ローカル開発環境の認証の設定をご覧ください。

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

フルフィルメント レスポンスを返す

次のサンプルは、フルフィルメント レスポンスを返す方法を示しています。

Go

Dialogflow CX への認証を行うには、アプリケーションのデフォルト認証情報を設定します。 詳細については、 ローカル開発環境の認証の設定をご覧ください。

Webhook クイックスタートをご覧ください。

Java

Dialogflow CX への認証を行うには、アプリケーションのデフォルト認証情報を設定します。 詳細については、 ローカル開発環境の認証の設定をご覧ください。


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

Dialogflow CX への認証を行うには、アプリケーションのデフォルト認証情報を設定します。 詳細については、 ローカル開発環境の認証の設定をご覧ください。

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

Dialogflow CX への認証を行うには、アプリケーションのデフォルト認証情報を設定します。 詳細については、 ローカル開発環境の認証の設定をご覧ください。

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

必要に応じてフォーム パラメータを設定する

次のサンプルは、パラメータに必須のフラグを付ける方法を示しています。

Java

Dialogflow CX への認証を行うには、アプリケーションのデフォルト認証情報を設定します。 詳細については、 ローカル開発環境の認証の設定をご覧ください。


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

Dialogflow CX への認証を行うには、アプリケーションのデフォルト認証情報を設定します。 詳細については、 ローカル開発環境の認証の設定をご覧ください。

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

フォーム パラメータを検証する

次のサンプルは、フォーム パラメータを検証する方法を示しています。

Java

Dialogflow CX への認証を行うには、アプリケーションのデフォルト認証情報を設定します。 詳細については、 ローカル開発環境の認証の設定をご覧ください。


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

Dialogflow CX への認証を行うには、アプリケーションのデフォルト認証情報を設定します。 詳細については、 ローカル開発環境の認証の設定をご覧ください。

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

Dialogflow CX への認証を行うには、アプリケーションのデフォルト認証情報を設定します。 詳細については、 ローカル開発環境の認証の設定をご覧ください。

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

次のサンプルは、Webhook リクエストの session ID をログに記録する方法を示しています。

Python

Dialogflow CX への認証を行うには、アプリケーションのデフォルト認証情報を設定します。 詳細については、 ローカル開発環境の認証の設定をご覧ください。


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

トラブルシューティング

Webhook 呼び出しのプロセス

Webhook 呼び出しは常に Dialogflow CX によって開始され、HTTPS 経由でウェブサーバーに送信されます。汎用ウェブサービス Webhook 呼び出しは、Google に属するインターネット IP アドレスから発信され、パブリック インターネットで利用可能なウェブサーバー(Webhook サーバー)に到達できます。 一方、Service Directory Webhook は常に内部 Google Cloud アドレスから開始され、プライベート ネットワーク 内 Google Cloudの Webhook サーバーにのみ到達できます。

Webhook のデバッグに役立つログ

Webhook の問題のデバッグでは通常、Cloud Logging Dialogflow CX ログと Webhook サーバーログを収集します。Webhook サーバーが Cloud Run functions を使用して実装されている場合、そのログは Cloud Logging にあります。それ以外の場合、ログは通常、Webhook サーバーが実行されている場所にあります。

標準の Webhook ログには、UUID を含む detectIntentResponseId フィールドが含まれています。これは、Webhook サーバーで特定の呼び出しをトレースするのに役立ちます。このログは、Cloud Logging が有効になっている場合、Dialogflow CX Cloud Logging ログに存在します。

Webhook に関する一般的な問題

Webhook 呼び出しの Dialogflow CX ログで見つかるエラーは次のとおりです。

Webhook サーバーのホスト名解決エラー

Dialogflow CX は汎用 Webhook のホスト名を検索しましたが、そのホスト名は DNS に存在しません。ホスト名がパブリック DNS に登録されていることを確認してください。ホスト名が新しい場合は、レコードが伝播するまでに時間がかかることがあります。Cloud Logging メッセージ: State: URL_ERROR, Reason: ERROR_DNS

Webhook サーバーがクライアントサイドのエラーを返す

ERROR_DNS を除き、この状態は Webhook サーバーからの 4xx レスポンスを示します。これは、未承認のステータス(401 - ERROR_AUTHENTICATION)であるか、Webhook サーバーで URL が見つからなかった(404 - ERROR_NOT_FOUND)可能性があります。Cloud Logging メッセージ: State: URL_ERROR

Webhook サーバーがレスポンスを返す前に Dialogflow エージェントがタイムアウトする

ウェブサーバーが完了する前に、Dialogflow CX が Webhook のタイムアウト上限に達しました。考えられるアプローチは 2 つあります。Webhook サーバーの処理時間を短縮するか、Dialogflow CX が Webhook を待機する時間を長くします。処理時間を短縮すると、多くの場合、最適な結果が得られますが、簡単ではありません。Webhook には最大タイムアウト時間があり、この設定を増やす前に、エンドユーザーまたはユーザーがエージェントからの回答を得るまでに時間がかかることを考慮してください。Cloud Logging メッセージ: State: URL_TIMEOUT, Reason: TIMEOUT_WEB

Webhook サーバーがレスポンスを返す前に gRPC がタイムアウトする

Webhook 呼び出しが完了する前に、Dialogflow CX API 呼び出しで gRPC によって設定された時間制限に達しました。この上限は通常、インテグレーション レベルで設定され、Dialogflow CX パラメータと Webhook のタイムアウト上限とは無関係です。gRPC の期限の詳細については、 https://grpc.io/docs/guides/deadlines/ をご覧ください。 Cloud Logging メッセージ: State: URL_REJECTED, Reason: REJECTED_DEADLINE_EXCEEDED

Dialogflow が Webhook サーバーに接続できなかった

ネットワーク エラーが原因で Webhook サーバーに到達できませんでした。または、接続が確立され、Webhook サーバーが HTTP ステータス 5xx を返しました。これは、リクエストの処理中に問題が発生したことを示します。Dialogflow CX がネットワーク レベルで Webhook サーバーのアドレスに到達できることを確認します。リクエストが Webhook サーバーログに表示される場合は、呼び出しが 5xx エラーを返した理由を確認します。Cloud Logging メッセージ: State: URL_UNREACHABLE

Webhook 呼び出しのトレース

標準の Webhook 呼び出しは、セッション ID、detectIntentResponse ID、Cloud Run functions のトレース ID、呼び出しのタイムスタンプを使用して、Dialogflow CX と Webhook サーバーの間で関連付けることができます。柔軟な Webhook トレースは、呼び出しのタイムスタンプと、設計時に Webhook 定義で指定されたセッション パラメータ値を使用して行うことができます。標準および柔軟な Webhook リクエストの詳細については、 Webhookをご覧ください。

セッション ID は、sessionInfo.session フィールドの WebhookRequestに表示されます。 このセッション ID は会話ごとに一意にする必要があります。このセッション ID を使用するとリクエストのエージェント ログと Webhook ログを比較する際に役立ちます。 前のログセッション IDセクション では、Webhook からセッション ID をログに記録する方法を示しています。

また、Webhook をホストしている場合は、 Cloud Run functions または同様の Google Cloud サーバーレス オプションを使用している場合は、 traceフィールドを ログエントリ からログフィルタとして使用します。 関数を 1 回実行すると、同じトレース値を持つ複数のログエントリが生成されます。

次の例では、セッション ID とトレース値の両方を使用して、特定の Dialogflow CX エージェント エラーログを対応する Cloud Run functions Webhook ログエントリに関連付けます。 この例では、 Cloud Logging を有効にしたエージェントに Cloud Logging フィルタ を使用します。

1. 特定のエージェントのエラーログに対して Dialogflow CX ログをフィルタする

次の Cloud Logging フィルタを使用して、特定のエージェントのエラーログに対して Dialogflow CX ログをフィルタします。

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

Webhook ログのエラーエントリは次のようになります。

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

セッション ID を含む labels.session_id フィールドをメモします。 このセッション ID は次のステップで使用します。

2. セッション ID で Cloud Run functions のログをフィルタする

次の Cloud Logging フィルタを使用して、セッション ID で Cloud Run functions のログをフィルタします。

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"

結果のログは、指定された セッション中に作成された Webhook ログに対応します。 次に例を示します。

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

trace フィールドをメモします。これは次のステップで使用します。

3. Cloud Functions のログを特定のトレースでフィルタする

次の Cloud Logging フィルタを使用して、特定のトレースのために Cloud Functions 関数のログをフィルタします。

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"

ここで、TRACE_ID はトレースの最後のセグメントです。たとえば、TRACE_IDprojects/PROJECT_ID/traces/e41eefc1fac48665b442bfa400cc2f5ee41eefc1fac48665b442bfa400cc2f5e です。

結果は、ステップ 1 のセッション ID とステップ 2 のトレースに関連付けられた Webhook リクエストの実行中に生成された Webhook サーバーログです。ログは次のようになります。

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