웹훅 구현

이 가이드에서는 웹훅 구현을 위한 다양한 샘플과 웹훅 문제 해결 권장사항을 제공합니다.

세션 매개변수 설정

다음 샘플은 세션 매개변수를 설정하는 방법을 보여줍니다.

Go

CTS에 인증하려면 애플리케이션 기본 사용자 인증 정보를 설정합니다. 자세한 내용은 로컬 개발 환경의 인증 설정을 참조하세요.

웹훅 빠른 시작을 참조하세요.

Java

CTS에 인증하려면 애플리케이션 기본 사용자 인증 정보를 설정합니다. 자세한 내용은 로컬 개발 환경의 인증 설정을 참조하세요.


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

CTS에 인증하려면 애플리케이션 기본 사용자 인증 정보를 설정합니다. 자세한 내용은 로컬 개발 환경의 인증 설정을 참조하세요.

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

CTS에 인증하려면 애플리케이션 기본 사용자 인증 정보를 설정합니다. 자세한 내용은 로컬 개발 환경의 인증 설정을 참조하세요.

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

fulfillment 응답 반환

다음 샘플은 fulfillment 응답을 반환하는 방법을 보여줍니다.

Go

CTS에 인증하려면 애플리케이션 기본 사용자 인증 정보를 설정합니다. 자세한 내용은 로컬 개발 환경의 인증 설정을 참조하세요.

웹훅 빠른 시작을 참조하세요.

Java

CTS에 인증하려면 애플리케이션 기본 사용자 인증 정보를 설정합니다. 자세한 내용은 로컬 개발 환경의 인증 설정을 참조하세요.


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

CTS에 인증하려면 애플리케이션 기본 사용자 인증 정보를 설정합니다. 자세한 내용은 로컬 개발 환경의 인증 설정을 참조하세요.

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

CTS에 인증하려면 애플리케이션 기본 사용자 인증 정보를 설정합니다. 자세한 내용은 로컬 개발 환경의 인증 설정을 참조하세요.

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

CTS에 인증하려면 애플리케이션 기본 사용자 인증 정보를 설정합니다. 자세한 내용은 로컬 개발 환경의 인증 설정을 참조하세요.


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

CTS에 인증하려면 애플리케이션 기본 사용자 인증 정보를 설정합니다. 자세한 내용은 로컬 개발 환경의 인증 설정을 참조하세요.

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

CTS에 인증하려면 애플리케이션 기본 사용자 인증 정보를 설정합니다. 자세한 내용은 로컬 개발 환경의 인증 설정을 참조하세요.


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

CTS에 인증하려면 애플리케이션 기본 사용자 인증 정보를 설정합니다. 자세한 내용은 로컬 개발 환경의 인증 설정을 참조하세요.

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

CTS에 인증하려면 애플리케이션 기본 사용자 인증 정보를 설정합니다. 자세한 내용은 로컬 개발 환경의 인증 설정을 참조하세요.

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 기록

다음 샘플은 웹훅 요청에서 session ID를 기록하는 방법을 보여줍니다.

Python

CTS에 인증하려면 애플리케이션 기본 사용자 인증 정보를 설정합니다. 자세한 내용은 로컬 개발 환경의 인증 설정을 참조하세요.


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

문제 해결

웹훅 호출의 수명

웹훅 호출은 항상 대화형 에이전트 (Dialogflow CX)에서 시작되며 HTTPS를 통해 웹 서버로 이동합니다. 일반 웹 서비스 웹훅 호출은 Google에 속한 인터넷 IP 주소에서 시작되며 공개 인터넷에서 사용할 수 있는 웹 서버 (웹훅 서버)에 도달할 수 있습니다. 반면 서비스 디렉터리 웹훅은 항상 내부 Google Cloud 주소에서 시작되며 Google Cloud 내 비공개 네트워크의 웹훅 서버에만 도달할 수 있습니다.

웹훅 디버깅에 유용한 로그

웹훅 문제를 디버그하려면 일반적으로 Cloud Logging Dialogflow 로그와 웹훅 서버 로그를 수집해야 합니다. 웹훅 서버가 Cloud Run 함수를 사용하여 구현된 경우 로그는 Cloud Logging에 있습니다. 그렇지 않으면 로그는 일반적으로 webhook 서버가 실행되는 위치에 있습니다.

표준 webhook 로그에는 UUID가 포함된 detectIntentResponseId 필드가 포함되어 있으며, 이는 webhook 서버에서 특정 호출을 추적하는 데 유용할 수 있습니다. 이 로그는 Cloud Logging이 사용 설정된 경우 Dialogflow Cloud Logging 로그에 있습니다.

일반적인 웹훅 문제

웹훅 호출에 관한 Dialogflow 로그에서 찾을 수 있는 일부 오류는 다음과 같습니다.

웹훅 서버 호스트 이름 확인 오류

Dialogflow에서 일반 웹훅의 호스트 이름을 조회했는데 DNS에 호스트 이름이 없습니다. 호스트 이름이 공개 DNS에 등록되어 있는지 확인합니다. 호스트 이름이 새 호스트 이름인 경우 레코드가 전파되는 데 다소 시간이 걸릴 수 있습니다. Cloud Logging 메시지: State: URL_ERROR, Reason: ERROR_DNS.

웹훅 서버가 클라이언트 측 오류를 반환함

ERROR_DNS 외에도 이 상태는 웹훅 서버의 4xx 응답을 나타냅니다. 승인되지 않은 상태 (401 - ERROR_AUTHENTICATION)이거나 webhook 서버에서 URL을 찾을 수 없는 경우 (404 - ERROR_NOT_FOUND)일 수 있습니다. Cloud Logging 메시지: State: URL_ERROR

웹훅 서버가 응답을 반환하기 전에 Dialogflow 에이전트 시간 초과

웹 서버가 완료되기 전에 Dialogflow가 웹훅 제한 시간에 도달했습니다. 여기서는 웹훅 서버 처리 시간을 줄이거나 Dialogflow가 웹훅을 기다리는 시간을 늘리는 두 가지 접근 방식을 사용할 수 있습니다. 처리 시간을 줄이면 일반적으로 최상의 결과를 얻을 수 있지만, 많은 경우 쉽지 않습니다. 웹훅에는 최대 시간 제한이 있으며 이 설정을 늘리기 전에 상담사로부터 답변을 받기 위해 최종 발신자 또는 사용자가 더 오래 기다려야 한다는 점에 유의하세요. Cloud Logging 메시지: State: URL_TIMEOUT, Reason: TIMEOUT_WEB

웹훅 서버가 응답을 반환하기 전에 gRPC 시간 초과

웹훅 호출이 완료되기 전에 Dialogflow API 호출에서 gRPC가 설정한 시간 제한에 도달했습니다. 이 한도는 일반적으로 통합 수준에서 설정되며 Dialogflow 매개변수 및 webhook 시간 제한과는 무관합니다. gRPC 기한에 관한 자세한 내용은 https://grpc.io/docs/guides/deadlines/를 참고하세요. Cloud Logging 메시지: State: URL_REJECTED, Reason: REJECTED_DEADLINE_EXCEEDED

Dialogflow가 웹훅 서버에 연결할 수 없음

네트워크 오류로 인해 웹훅 서버에 연결할 수 없거나 연결이 설정되었으나 웹훅 서버가 요청을 처리하는 동안 문제를 나타내는 HTTP 상태 5xx를 반환했습니다. Dialogflow가 네트워킹 수준에서 웹훅 서버 주소에 연결할 수 있는지 확인합니다. 요청이 웹훅 서버 로그에 표시되면 호출에서 5xx 오류를 반환한 이유를 찾습니다. Cloud Logging 메시지: State: URL_UNREACHABLE.

웹훅 호출 추적

표준 웹훅 호출은 세션 ID, detectIntentResponse ID, Cloud Run 함수의 트레이스 ID, 호출 타임스탬프를 사용하여 Dialogflow와 웹훅 서버 간에 연결할 수 있습니다. 유연한 웹훅 추적은 호출의 타임스탬프와 디자인 시 웹훅 정의에 지정된 세션 매개변수 값을 사용하여 실행할 수 있습니다. 표준 및 유연한 웹훅 요청에 관한 자세한 내용은 웹훅을 참고하세요.

세션 ID는 WebhookRequestsessionInfo.session 필드에 표시됩니다. 이 세션 ID는 대화마다 고유해야 하며 동일한 세션 ID를 사용하는 요청에 대해 상담사 로그와 웹훅 로그를 비교하는 데 도움이 될 수 있습니다. 이전의 세션 ID 기록 섹션에서는 웹훅에서 세션 ID를 기록하는 방법을 보여줍니다.

또한 Cloud Run 함수 또는 유사한 Google Cloud 서버리스 옵션에 웹훅을 호스팅하는 경우 로그 항목trace 필드를 로그 필터로 사용할 수 있습니다. 함수를 한 번 실행하면 동일한 trace 값을 가진 여러 로그 항목이 생성됩니다.

다음 예에서는 세션 ID와 trace 값을 모두 사용하여 특정 Dialogflow 에이전트 오류 로그를 해당 Cloud Run 함수 웹훅 로그 항목과 연결합니다. 이 예시에서는 Cloud Logging을 사용 설정한 에이전트에 Cloud Logging 필터를 사용합니다.

1. 특정 에이전트의 오류 로그에 대한 Dialogflow 로그 필터링

다음 Cloud Logging 필터를 사용하여 특정 에이전트의 오류 로그에 대한 Dialogflow 로그를 필터링합니다.

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

웹훅 로그 오류 항목은 다음과 같습니다.

{
  "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 함수 로그 필터링

다음 Cloud Logging 필터를 사용하여 세션 ID별로 Cloud Run 함수 로그를 필터링합니다.

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"

결과 로그는 제공된 세션 중에 작성된 웹훅 로그에 해당합니다. 예를 들면 다음과 같습니다.

{
  "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. 특정 trace에 대한 Cloud 함수 로그 필터링

다음 Cloud Logging 필터를 사용하여 특정 trace에 대한 Cloud 함수 로그를 필터링합니다.

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의 마지막 세그먼트입니다. 예를 들어 projects/PROJECT_ID/traces/e41eefc1fac48665b442bfa400cc2f5eTRACE_IDe41eefc1fac48665b442bfa400cc2f5e입니다.

그 결과로 생성되는 로그는 1단계의 세션 ID와 2단계의 trace와 연결된 웹훅 요청을 실행하는 동안 생성된 웹훅 서버 로그입니다. 로그는 다음과 같이 표시됩니다.

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