檢測 Google Cloud Python 用戶端程式庫

本指南說明如何在 Google Cloud Python 用戶端程式庫中,設定及使用 OpenTelemetry 分散式追蹤。

總覽

Google Cloud Python 用戶端程式庫提供內建的 OpenTelemetry 分散式追蹤功能。這項檢測功能可讓您深入瞭解用戶端作業、RPC 叫用、重試行為、網路延遲和服務回應,無須手動進行 monkey-patching。

主要特色:

  • 不限後端:發出標準 OpenTelemetry 跨度。您可以直接將追蹤記錄匯出至 Cloud Trace、地端部署 OpenTelemetry Collector 或第三方觀測平台。
  • 選擇加入:分散式追蹤預設為停用,避免不需要遙測的應用程式產生執行階段負擔。
  • 內容傳播:Span 會使用 Python 內建的 contextvars,自動繫結至有效的 OpenTelemetry 追蹤記錄相關資訊,將用戶端呼叫與傳入的 HTTP/gRPC 要求建立關聯。

追蹤記錄的運作方式 (Span 階層)

啟用後, Google Cloud Python 用戶端程式庫會發出階層式兩層 span 架構,明確區分面向使用者的執行方法和基礎連線嘗試:

[Logical Client Method Span] (Parent: covers full method duration, retries, and backoff)
 │
 ├── [Network Attempt Span #1] (Child: First wire call; e.g. transient 503 UNAVAILABLE)
 └── [Network Attempt Span #2] (Child: Retry wire call; succeeds 200 OK)

1. 邏輯用戶端方法 Span (父項)

  • 範圍:封裝整個用戶端程式庫方法呼叫生命週期,從叫用到完成。
  • 時間長度:涵蓋所有重試、指數輪詢暫停和逾時政策。
  • Identity:以完整 RPC 方法命名 (例如 google.cloud.secretmanager.v1.SecretManagerService/GetSecretVersion)。
  • 屬性:擷取邏輯 RPC 中繼資料、目的地服務和最終高階結果。

2. 網路嘗試時間範圍 (子項)

  • 範圍:建立為邏輯方法 Span 的子 Span,代表個別 HTTP/REST 或 gRPC 實體網路嘗試。
  • 生命週期:每次嘗試連線網路時,系統都會產生新的 Span。如果作業在第一次嘗試時成功,系統會記錄一個子項 span。如果作業遇到暫時性錯誤並重試,每次嘗試都會記錄為獨立的子項 span,並有自己的時間和狀態。
  • 屬性:擷取低階連線狀態碼、目的地伺服器位址和傳輸詳細資料。

事前準備和安裝

Google Cloud Python 用戶端程式庫追蹤功能仰賴標準 OpenTelemetry Python 套件。

1. 安裝套件

  • 用戶端程式庫和 gRPC 傳輸檢測:

    • opentelemetry-api 會與 google-api-core 一起自動安裝,以支援邏輯方法 span 和 HTTP/REST (rest) 傳輸 span。
    • 如要一併記錄低階 gRPC 傳輸 span,請安裝用戶端程式庫和 google-api-core[tracing] (會安裝 opentelemetry-instrumentation-grpc):
    pip install google-cloud-secret-manager "google-api-core[tracing]"
    
  • OpenTelemetry SDK (適用於獨立應用程式和程式碼範例):

    • 如果環境已提供 TracerProvider,用戶端程式庫就不需要 opentelemetry-sdk。
    • 不過,如要設定 TracerProvider 並在自己的程式碼中匯出 span (包括本頁中的範例),請安裝 opentelemetry-sdk:
    pip install opentelemetry-sdk
    

如要瞭解如何設定 OpenTelemetry 匯出工具,將 span 傳送至 Cloud Trace 或正式環境中的 OpenTelemetry 收集器,請參閱「使用 OpenTelemetry 設定 Python」和「選擇檢測方法」。

啟用追蹤功能

分散式追蹤功能可以透過環境變數在全域啟用,也可以透過程式輔助方式在每個用戶端啟用。使用 ClientOptions 傳遞的個別用戶端設定,優先順序高於環境變數設定。

選項 1:全域設定 (環境變數)

如要在環境中為所有支援的 Google Cloud Python 用戶端程式庫啟用追蹤功能,請在啟動應用程式前設定下列環境變數:

export GOOGLE_SDK_PYTHON_TRACING_ENABLED=true

設為 true 時,用戶端程式庫會自動偵測全域註冊的 OpenTelemetry TracerProvider,並為所有用戶端叫用發出 span。

方法 2:個別用戶端設定 (程式碼)

如要進行精細控管或多租戶應用程式,請使用 ClientOptions 傳遞 tracer_provider,設定特定用戶端執行個體:

from google.api_core.client_options import ClientOptions
from google.cloud import secretmanager

options = ClientOptions(tracer_provider=my_tracer_provider)
client = secretmanager.SecretManagerServiceClient(client_options=options)

程式碼範例

用戶端程式庫可以使用應用程式預設憑證,輕鬆向 Google API 進行驗證,並向這些 API 傳送要求。有了應用程式預設憑證,您可以在本機測試應用程式,並在不變更基礎程式碼的情況下部署應用程式。詳情請參閱「 進行驗證以使用用戶端程式庫」一文。

1. 快速入門導覽課程範例 (SecretManagerServiceClient)

下列獨立範例示範如何設定標準 OpenTelemetry、使用環境變數啟用用戶端程式庫追蹤,以及使用 ConsoleSpanExporter 將發出的 span 直接以 JSON 格式輸出至終端機。

import os

from google.cloud import secretmanager
from opentelemetry import trace
from opentelemetry.sdk.trace import TracerProvider
from opentelemetry.sdk.trace.export import ConsoleSpanExporter, SimpleSpanProcessor


def get_secret_version_with_tracing(
    project_id: str,
    secret_id: str,
    version_id: str = "latest",
) -> secretmanager.SecretVersion:
    """Get a secret version in Secret Manager with OpenTelemetry tracing enabled.

    Args:
        project_id: Google Cloud project ID.
        secret_id: ID of the secret.
        version_id: ID of the secret version (defaults to "latest").

    Returns:
        The SecretVersion metadata object.
    """
    # NOTE: In standalone scripts or CLI tools, initialize and shut down the
    # TracerProvider within the script workflow. In long-running production
    # applications (e.g., web servers), configure the TracerProvider once at
    # application startup.
    #
    # Initialize the OpenTelemetry TracerProvider with a Console exporter
    provider = TracerProvider()
    provider.add_span_processor(SimpleSpanProcessor(ConsoleSpanExporter()))
    trace.set_tracer_provider(provider)

    # Enable Google Cloud client library tracing
    os.environ["GOOGLE_SDK_PYTHON_TRACING_ENABLED"] = "true"

    # Instantiate the client (automatically discovers the active TracerProvider)
    client = secretmanager.SecretManagerServiceClient()

    # Construct the resource name and invoke the RPC
    name = f"projects/{project_id}/secrets/{secret_id}/versions/{version_id}"

    try:
        print("--- OpenTelemetry Trace Spans (JSON) ---")
        response = client.get_secret_version(request={"name": name})
        state_name = response.state.name
        print(
            f"\nAPI Result: Retrieved secret version {response.name} (state: {state_name})"
        )
        return response
    finally:
        # Flush buffered spans before program completion
        provider.shutdown()

2. 程式輔助設定 (ClientOptions)

如果不想使用環境變數,或需要將不同的 TracerProvider 執行個體傳遞至不同的用戶端,請使用 ClientOptions 傳遞 tracer_provider,以程式輔助方式設定用戶端:

from google.api_core.client_options import ClientOptions
from google.cloud import secretmanager
from opentelemetry.sdk.trace import TracerProvider
from opentelemetry.sdk.trace.export import ConsoleSpanExporter, SimpleSpanProcessor


def get_secret_version_with_client_options(
    project_id: str,
    secret_id: str,
    version_id: str = "latest",
) -> secretmanager.SecretVersion:
    """Get a secret version configuring tracing programmatically via ClientOptions.

    Args:
        project_id: Google Cloud project ID.
        secret_id: ID of the secret.
        version_id: ID of the secret version (defaults to "latest").

    Returns:
        The SecretVersion metadata object.
    """
    # Initialize an independent TracerProvider (no global registration required)
    provider = TracerProvider()
    provider.add_span_processor(SimpleSpanProcessor(ConsoleSpanExporter()))

    # Pass the TracerProvider directly via ClientOptions
    # Tracing is activated specifically for this client instance, even without
    # setting the GOOGLE_SDK_PYTHON_TRACING_ENABLED environment variable.
    options = ClientOptions(tracer_provider=provider)
    client = secretmanager.SecretManagerServiceClient(client_options=options)

    # Construct resource name and invoke RPC
    name = f"projects/{project_id}/secrets/{secret_id}/versions/{version_id}"

    try:
        print("--- OpenTelemetry Trace Spans (JSON) ---")
        response = client.get_secret_version(request={"name": name})
        state_name = response.state.name
        print(
            f"\nAPI Result: Retrieved secret version {response.name} (state: {state_name})"
        )
        return response
    finally:
        # Flush buffered spans before program completion
        provider.shutdown()

3. 非同步用戶端範例 (SecretManagerServiceAsyncClient)

以下範例使用 SecretManagerServiceAsyncClient 定義非同步協同程式 (async def get_secret_version_with_tracing_async)。由於這個用戶端是非同步,請務必在有效的 asyncio 事件迴圈中執行。

import asyncio
import os

from google.cloud import secretmanager
from opentelemetry import trace
from opentelemetry.sdk.trace import TracerProvider
from opentelemetry.sdk.trace.export import ConsoleSpanExporter, SimpleSpanProcessor


async def get_secret_version_with_tracing_async(
    project_id: str,
    secret_id: str,
    version_id: str = "latest",
) -> secretmanager.SecretVersion:
    """Get a secret version using SecretManagerServiceAsyncClient with OpenTelemetry tracing.

    Args:
        project_id: Google Cloud project ID.
        secret_id: ID of the secret.
        version_id: ID of the secret version (defaults to "latest").

    Returns:
        The SecretVersion metadata object.
    """
    # NOTE: In standalone scripts or CLI tools, initialize and shut down the
    # TracerProvider within the script workflow. In long-running production
    # applications (e.g., web servers), configure the TracerProvider once at
    # application startup.
    #
    # Initialize the OpenTelemetry TracerProvider with a Console exporter
    provider = TracerProvider()
    provider.add_span_processor(SimpleSpanProcessor(ConsoleSpanExporter()))
    trace.set_tracer_provider(provider)

    # Enable Google Cloud client library tracing
    os.environ["GOOGLE_SDK_PYTHON_TRACING_ENABLED"] = "true"

    # Instantiate the async client
    client = secretmanager.SecretManagerServiceAsyncClient()

    # Construct resource name and invoke the async RPC
    name = f"projects/{project_id}/secrets/{secret_id}/versions/{version_id}"

    try:
        print("--- OpenTelemetry Trace Spans (JSON) ---")
        response = await client.get_secret_version(request={"name": name})
        state_name = response.state.name
        print(
            f"\nAPI Result: Retrieved secret version {response.name} (state: {state_name})"
        )
        return response
    finally:
        # Flush buffered spans before program completion
        provider.shutdown()

語意屬性參考資料

Google Cloud Python 用戶端程式庫發出的 Span 遵循標準 OpenTelemetry 語意慣例 (適用於 RPC Span),記錄傳輸通訊協定、RPC 方法身分、目的地伺服器位址、回應狀態碼和錯誤詳細資料的標準中繼資料。您可以使用這些屬性,在觀測能力或 Cloud Trace 資訊主頁中篩選、匯總及建立警告政策。

安全性與機密資料

Google Cloud Python 用戶端程式庫檢測功能遵循嚴格的安全性和隱私權標準:

  • 酬載保護:用戶端程式庫絕不在追蹤記錄 span 上記錄要求或回應酬載資料 (例如檔案內容、密鑰值或資料庫查詢結果)。
  • ID 顯示設定:資源名稱 (例如專案 ID、資料集 ID 和 Secret 名稱) 會顯示在方法參數和網址端點屬性中。如果資源 ID 含有機密業務資訊,請確保追蹤記錄儲存空間符合內部法規遵循政策。
  • 第三方匯出工具:將追蹤記錄匯出至第三方觀測服務或軟體式服務 (SaaS) 供應商時,請詳閱貴組織的資料保護協議,並視需要設定匯出工具屬性篩選功能。