הוספת כלים לספריות הלקוח של Python ב-Google Cloud

במדריך הזה נסביר איך להגדיר מעקב מבוזר של OpenTelemetry בספריות הלקוח של Google Cloud ב-Python, ואיך להשתמש בו.

סקירה כללית

Google Cloud ספריות הלקוח של Python מספקות מעקב מבוזר מובנה של OpenTelemetry. הכלים האלה מאפשרים לראות לעומק את פעולות הלקוח, קריאות RPC, התנהגות של ניסיונות חוזרים, זמן אחזור ברשת ותגובות של שירותים, בלי צורך בתיקון ידני של קוד בזמן ריצה.

מאפיינים מרכזיים:

  • לא תלוי בקצה העורפי: פולט טווחי OpenTelemetry סטנדרטיים. אתם יכולים לייצא את נתוני המעקב ישירות ל-Cloud Trace, ל-OpenTelemetry Collector מקומי או לפלטפורמות של צד שלישי לתצפיתיות.
  • הצטרפות: מעקב מבוזר מושבת כברירת מחדל כדי למנוע תקורה בזמן ריצה באפליקציות שלא דורשות טלמטריה.
  • הפצת הקשר: יחידות לוגיות למעקב נקשרות באופן אוטומטי להקשר יומן המעקב הפעיל של OpenTelemetry באמצעות contextvars המובנה של Python, ומתאמות בין קריאות הלקוח לבין בקשות HTTP/gRPC נכנסות.

איך פועל המעקב (היררכיית טווחים)

כשהתכונה מופעלת, Google Cloud ספריות הלקוח של Python יוצרות ארכיטקטורת span היררכית בשתי רמות, שמפרידה באופן ברור בין הפעלת השיטה שגלויה למשתמשים לבין ניסיונות ה-wire הבסיסיים:

[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. טווחים של שיטות לוגיות בצד הלקוח (הורה)

  • היקף: כולל את כל מחזור החיים של הפעלת ה-method בספריית הלקוח, מההפעלה ועד לסיום.
  • משך הזמן: כולל את כל הניסיונות החוזרים, ההשהיות המעריכיות לפני ניסיון חוזר (exponential backoff) וכללי המדיניות של זמן קצוב לתפוגה.
  • זהות: נקראת על שם ה-RPC method שמוגדרת במלואה (לדוגמה, google.cloud.secretmanager.v1.SecretManagerService/GetSecretVersion).
  • מאפיינים: מתעדים מטא-נתונים לוגיים של RPC, שירות היעד והתוצאה הסופית ברמה גבוהה.

2. טווחים של ניסיונות ברשת (צאצא)

  • היקף: נוצר כ-child span של ה-span של השיטה הלוגית, ומייצג ניסיונות של רשת פיזית של HTTP/REST או gRPC.
  • מחזור חיים: טווח חדש נוצר לכל ניסיון של הרשת. אם פעולה מצליחה בניסיון הראשון, מתועד בדיוק span צאצא אחד. אם פעולה נתקלת בשגיאות זמניות ומנסה שוב, כל ניסיון מתועד כטווח צאצא נפרד עם תזמון וסטטוס משלו.
  • מאפיינים: מתעדים קודי סטטוס של חיבורים ברמה נמוכה, כתובת שרת היעד ופרטי העברה.

דרישות מוקדמות והתקנה

Google Cloud המעקב בספריית הלקוח של Python מסתמך על חבילות OpenTelemetry Python רגילות.

1. התקנת חבילות

  • ספריית לקוח וכלים להעברת gRPC:

    • ‫opentelemetry-api מותקן באופן אוטומטי עם google-api-core כדי לתמוך בטווחים של שיטות לוגיות ובטווחים של העברת HTTP/REST (rest).
    • כדי לתעד גם טווחי זמן של העברת gRPC ברמה נמוכה, מתקינים את ספריית הלקוח יחד עם google-api-core[tracing] (שמתקינה את opentelemetry-instrumentation-grpc):
    pip install google-cloud-secret-manager "google-api-core[tracing]"
    
  • SDK OpenTelemetry (לאפליקציות עצמאיות ודוגמאות קוד):

    • ספריות הלקוח לא דורשות opentelemetry-sdk אם הסביבה שלכם כבר מספקת TracerProvider.
    • עם זאת, כדי להגדיר TracerProvider ולייצא טווחי זמן בקוד שלכם (כולל הדוגמאות שבדף הזה), צריך להתקין את opentelemetry-sdk:
    pip install opentelemetry-sdk
    

במאמרים הגדרת Python באמצעות OpenTelemetry ובחירת גישה למדידת ביצועים מוסבר איך להגדיר את כלי הייצוא של OpenTelemetry כדי לשלוח טווחי זמן ל-Cloud Trace או לאספן של OpenTelemetry בסביבת הייצור.

הפעלת מעקב

אפשר להפעיל מעקב מבוזר באופן גלובלי באמצעות משתנה סביבה, או באופן פרוגרמטי לכל לקוח בנפרד. הגדרות לכל לקוח שמועברות באמצעות ClientOptions מקבלות קדימות על פני הגדרות של משתני סביבה.

אפשרות 1: הגדרה גלובלית (משתני סביבה)

כדי להפעיל מעקב בכל ספריות הלקוח הנתמכות של Google Cloud Python בסביבה שלכם, הגדירו את משתנה הסביבה הבא לפני הפעלת האפליקציה:

export GOOGLE_SDK_PYTHON_TRACING_ENABLED=true

כשמגדירים את המשתנה לערך true, ספריות הלקוח מזהות באופן אוטומטי את TracerProvider של OpenTelemetry שרשום באופן גלובלי, ויוצרות טווחי זמן לכל הקריאות של הלקוח.

אפשרות 2: הגדרה לכל לקוח (קוד)

כדי לשלוט בצורה מדויקת יותר או להשתמש באפליקציות עם כמה דיירים, צריך להגדיר מכונה ספציפית של לקוח על ידי העברת tracer_provider באמצעות ClientOptions:

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)

דוגמאות לקוד

בספריות הלקוח אפשר להשתמש ב-Application Default Credentials כדי לעבור בקלות אימות מול Google APIs ולשלוח בקשות לאותם ממשקי API. באמצעות Application Default Credentials, אתם יכולים לבדוק את האפליקציה ברמה המקומית ולפרוס אותה בלי לשנות את הקוד שלה. מידע נוסף זמין במאמר אימות לצורך שימוש בספריות לקוח.

1. דוגמה למדריך למתחילים (SecretManagerServiceClient)

הדוגמה הבאה, שמכילה את כל מה שצריך, ממחישה איך להגדיר OpenTelemetry סטנדרטי, להפעיל מעקב של ספריית לקוח באמצעות משתנה סביבה ולהדפיס טווחים שנשלחו ישירות למסוף כ-JSON באמצעות ConsoleSpanExporter.

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 ללקוחות שונים, אתם יכולים להגדיר לקוח באופן פרוגרמטי על ידי העברת tracer_provider באמצעות ClientOptions:

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)

הדוגמה הבאה מגדירה קורוטינה אסינכרונית (async def get_secret_version_with_tracing_async) באמצעות SecretManagerServiceAsyncClient. הלקוח הזה הוא אסינכרוני, לכן צריך להפעיל אותו בתוך לולאת אירוע פעילה של 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 תואמים למוסכמות הסמנטיות הרגילות של OpenTelemetry לטווחי RPC, ומתעדים מטא-נתונים רגילים של פרוטוקול התעבורה, מזהה שיטת ה-RPC, כתובת שרת היעד, קודי סטטוס של התגובה ופרטי השגיאה. אתם יכולים להשתמש במאפיינים האלה כדי לסנן, לצבור וליצור מדיניות התראות בלוח הבקרה של יכולת התצפית או של Cloud Trace.

אבטחה ומידע אישי רגיש

Google Cloud האינסטרומנטציה של ספריית הלקוח ב-Python תוכננה בהתאם לתקני אבטחה ופרטיות מחמירים:

  • הגנה על המטען הייעודי (payload): ספריות הלקוח אף פעם לא מתעדות נתוני מטען ייעודי של בקשות או תגובות (כמו תוכן של קבצים, ערכים סודיים או תוצאות של שאילתות במסד נתונים) בטווחים של מעקב.
  • חשיפת מזהים: שמות של משאבים (כמו מזהי פרויקטים, מזהי מערכי נתונים ושמות של סודות) מופיעים בפרמטרים של שיטות ובמאפיינים של נקודות קצה של כתובות URL. אם מזהי המשאבים מכילים מידע עסקי רגיש, ודאו שאחסון המעקב תואם למדיניות התאימות הפנימית שלכם.
  • מייצאים של צד שלישי: כשמייצאים נתוני מעקב לשירותי צד שלישי של ניטור או לספקי SaaS, צריך לבדוק את הסכמי ההגנה על הנתונים של הארגון ולהגדיר סינון של מאפייני המייצאים לפי הצורך.