ورود به سیستم

ثبت و نظارت به صورت پشت سر هم کار می کنند تا به شما در درک و بهینه سازی عملکرد برنامه و همچنین تشخیص خطاها و مسائل مربوط به سیستم کمک کنند. باید گزارش‌های خلاصه برای همه تماس‌های API و گزارش‌های دقیق برای تماس‌های ناموفق API را روشن کنید تا بتوانید گزارش تماس‌های API را در صورت نیاز به پشتیبانی فنی ارائه کنید.

ثبت کتابخانه مشتری

کتابخانه های سرویس گیرنده Google Ads API با ورود به سیستم همراه است. برای جزئیات ورود به سیستم مخصوص پلت فرم، به اسناد ورود به سیستم در کتابخانه مشتری انتخابی خود مراجعه کنید.

زبان راهنما
جاوا ثبت اسناد برای جاوا
دات نت ثبت اسناد برای دات نت
PHP ثبت اسناد برای PHP
پایتون ثبت اسناد برای پایتون
روبی ثبت اسناد برای روبی
پرل ثبت اسناد برای پرل

فرمت گزارش

کتابخانه های سرویس گیرنده Google Ads API یک گزارش دقیق و یک گزارش خلاصه برای هر تماس API ایجاد می کنند. گزارش تفصیلی شامل تمام جزئیات تماس API است، در حالی که گزارش خلاصه حاوی حداقل جزئیات تماس API است. نمونه ای از هر نوع گزارش نشان داده شده است، با لاگ ها کوتاه شده و برای خوانایی قالب بندی شده اند.

گزارش خلاصه

GoogleAds.SummaryRequestLogs Warning: 1 : [2023-09-15 19:58:39Z] -
Request made: Host: , Method: /google.ads.googleads.v14.services.GoogleAdsService/SearchStream,
ClientCustomerID: 5951878031, RequestID: hELhBPNlEDd8mWYcZu7b8g,
IsFault: True, FaultMessage: Status(StatusCode="InvalidArgument",
Detail="Request contains an invalid argument.")

گزارش تفصیلی

GoogleAds.DetailedRequestLogs Verbose: 1 : [2023-11-02 21:09:36Z] -
---------------BEGIN API CALL---------------

Request
-------

Method Name: /google.ads.googleads.v14.services.GoogleAdsService/SearchStream
Host:
Headers: {
  "x-goog-api-client": "gl-dotnet/5.0.0 gapic/17.0.1 gax/4.2.0 grpc/2.46.3 gccl/3.0.1 pb/3.21.5",
  "developer-token": "REDACTED",
  "login-customer-id": "1234567890",
  "x-goog-request-params": "customer_id=4567890123"
}

{ "customerId": "4567890123", "query": "SELECT ad_group_criterion.type FROM
  ad_group_criterion WHERE ad_group.status IN(ENABLED, PAUSED) AND
  campaign.status IN(ENABLED, PAUSED) ", "summaryRowSetting": "NO_SUMMARY_ROW" }

Response
--------
Headers: {
  "date": "Thu, 02 Nov 2023 21:09:35 GMT",
  "alt-svc": "h3-29=\":443\"; ma=2592000"
}

{
  "results": [ {
    "adGroupCriterion": {
      "resourceName": "customers/4567890123/adGroupCriteria/456789456789~123456123467",
      "type": "KEYWORD"
    } }, {
    "adGroupCriterion": {
      "resourceName": "customers/4567890123/adGroupCriteria/456789456789~56789056788",
      "type": "KEYWORD"
    } } ],
    "fieldMask": "adGroupCriterion.type", "requestId": "VsJ4F00ew6s9heHvAJ-abw"
}
----------------END API CALL----------------

اگر از کتابخانه مشتری استفاده نکنم چه می شود؟

اگر از کتابخانه سرویس گیرنده استفاده نمی کنید، ثبت گزارش خود را برای ثبت جزئیات تماس های API خروجی و ورودی پیاده سازی کنید. شما باید حداقل مقدار request-id را وارد کنید، که در صورت لزوم می‌تواند با تیم‌های پشتیبانی فنی به اشتراک گذاشته شود.

ورود به ابر

ابزارهای زیادی وجود دارد که می توانید از آنها برای ثبت گزارش ها و معیارهای عملکرد برنامه خود استفاده کنید. برای مثال، می‌توانید از Google Cloud Logging برای ثبت معیارهای عملکرد در پروژه Google Cloud خود استفاده کنید. این امکان راه اندازی داشبورد و هشدار در Google Cloud Monitoring را برای استفاده از معیارهای ثبت شده فراهم می کند.

Cloud Logging کتابخانه‌های سرویس گیرنده را برای همه زبان‌های کتابخانه سرویس گیرنده Google Ads API به جز Perl ارائه می‌کند، بنابراین در بیشتر موارد می‌توان با Cloud Logging مستقیماً از ادغام کتابخانه مشتری خود وارد سیستم شوید. برای سایر زبان‌ها از جمله Perl، Cloud Logging یک REST API را نیز ارائه می‌کند.

چند گزینه برای ورود به Cloud Logging یا ابزار دیگری از کتابخانه سرویس گیرنده Google Ads API وجود دارد. هر گزینه با معاوضه های زمان اجرا، پیچیدگی و عملکرد خود همراه است. قبل از اینکه تصمیم بگیرید کدام راه حل را اجرا کنید، به دقت در مورد این مبادلات فکر کنید.

گزینه 1: گزارش‌های محلی را از فرآیند پس‌زمینه در فضای ابری بنویسید

گزارش‌های کتابخانه مشتری را می‌توان با تغییر پیکربندی گزارش‌گیری در یک فایل محلی روی دستگاه شما نوشت. هنگامی که گزارش‌ها به یک فایل محلی خروجی می‌شوند، می‌توانید یک شبح برای جمع‌آوری گزارش‌ها و ارسال آن‌ها به ابر تنظیم کنید.

یکی از محدودیت‌های این رویکرد این است که برخی از معیارهای عملکرد به‌طور پیش‌فرض ثبت نمی‌شوند. گزارش‌های کتابخانه مشتری شامل جزئیاتی از اشیاء درخواست و پاسخ است، بنابراین معیارهای تأخیر گنجانده نمی‌شوند مگر اینکه تغییرات اضافی برای ثبت این موارد نیز ایجاد شود.

گزینه 2: برنامه خود را روی Compute Engine اجرا کنید و Ops Agent را نصب کنید

اگر برنامه شما روی Compute Engine اجرا می شود، می توانید با نصب Ops Agent گزارش های خود را به Google Cloud Logging ارسال کنید. عامل Ops را می توان طوری پیکربندی کرد که گزارش های برنامه شما را به Cloud Logging ارسال کند، علاوه بر سنجه ها و گزارش هایی که به طور پیش فرض ارسال می شوند .

اگر برنامه شما در حال حاضر در یک محیط Google Cloud اجرا می شود، یا اگر قصد دارید برنامه خود را به Google Cloud منتقل کنید، این گزینه عالی برای بررسی است.

گزینه 3: ورود به کد برنامه خود را پیاده سازی کنید

ورود مستقیم از کد برنامه را می توان به یکی از دو روش انجام داد:

  1. ترکیب محاسبات معیارها و بیانیه های گزارش در هر مکان قابل اجرا در کد شما. این گزینه برای پایگاه های کد کوچکتر امکان پذیرتر است، جایی که دامنه و هزینه های نگهداری چنین تغییری حداقل است.

  2. پیاده سازی یک رابط ورود به سیستم. اگر بتوان منطق برنامه را انتزاع کرد به طوری که قطعات مختلف برنامه از یک کلاس پایه به ارث می برند، منطق ورود به سیستم را می توان در آن کلاس پایه پیاده سازی کرد. این گزینه به طور کلی بر ترکیب عبارات گزارش در سراسر کد برنامه ترجیح داده می شود، زیرا نگهداری و مقیاس آن آسان تر است. برای پایگاه های کد بزرگتر، قابلیت نگهداری و مقیاس پذیری این راه حل بسیار مرتبط است.

یکی از محدودیت‌های این رویکرد این است که گزارش‌های درخواست و پاسخ کامل از کد برنامه در دسترس نیستند. اشیاء درخواست و پاسخ کامل از رهگیرهای gRPC قابل دسترسی هستند. اینگونه است که لاگ کتابخانه داخلی سرویس گیرنده گزارش های درخواست و پاسخ را به دست می آورد. در صورت بروز خطا، اطلاعات اضافی ممکن است در شیء استثنا موجود باشد، اما جزئیات کمتری برای پاسخ‌های موفق در منطق برنامه موجود است. به عنوان مثال، در بیشتر موارد، شناسه درخواست برای یک درخواست موفق از اشیاء پاسخ API Google Ads قابل دسترسی نیست.

گزینه 4: یک رهگیر ثبت سفارشی gRPC را پیاده سازی کنید

gRPC از رهگیرهای یکپارچه و جریانی پشتیبانی می کند که می توانند به اشیاء درخواست و پاسخ هنگام عبور بین مشتری و سرور دسترسی داشته باشند. کتابخانه های سرویس گیرنده Google Ads API از رهگیرهای gRPC برای ارائه پشتیبانی از ورود به سیستم استفاده می کنند. به طور مشابه، می توانید یک رهگیر gRPC سفارشی برای دسترسی به اشیاء درخواست و پاسخ، استخراج اطلاعات برای اهداف ثبت و نظارت، و نوشتن آن داده ها در مکان مورد نظر خود پیاده سازی کنید.

بر خلاف برخی از راه حل های دیگر ارائه شده در اینجا، پیاده سازی یک رهگیر gRPC سفارشی به شما انعطاف پذیری برای گرفتن درخواست و اشیاء پاسخ در هر درخواست، و پیاده سازی منطق اضافی برای گرفتن جزئیات درخواست را می دهد. برای مثال، می‌توانید زمان سپری شده یک درخواست را با اجرای منطق زمان‌بندی عملکرد در خود رهگیر سفارشی محاسبه کنید، سپس معیار را در Google Cloud Logging ثبت کنید تا آن را برای نظارت بر تأخیر در Google Cloud Monitoring در دسترس قرار دهید.

رهگیر سفارشی Google Cloud Logging در پایتون

برای نشان دادن این راه حل، نمونه ای از یک رهگیر ثبت سفارشی در پایتون را نوشته ایم. رهگیر سفارشی ایجاد شده و به سرویس گیرنده ارسال می شود. سپس به اشیاء درخواست و پاسخی که در هر فراخوانی روش سرویس ارسال می‌شوند دسترسی پیدا می‌کند، داده‌های آن اشیاء را پردازش می‌کند و داده‌ها را به Google Cloud Logging ارسال می‌کند.

علاوه بر داده‌هایی که از اشیاء درخواست و پاسخ به دست می‌آیند، مثال، منطق اضافی را برای ثبت زمان سپری شده درخواست، و برخی ابرداده‌های دیگر که برای اهداف نظارتی مفید هستند، مانند موفقیت یا عدم موفقیت درخواست، پیاده‌سازی می‌کند. برای اطلاعات بیشتر در مورد اینکه چگونه این اطلاعات می تواند مفید باشد، چه به طور کلی برای نظارت، و چه به طور خاص هنگام ترکیب Google Cloud Logging و Google Cloud Monitoring، به راهنمای نظارت مراجعه کنید.

# Copyright 2022 Google LLC
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#     https://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
"""A custom gRPC Interceptor that logs requests and responses to Cloud Logging.

The custom interceptor object is passed into the get_service method of the
GoogleAdsClient. It intercepts requests and responses, parses them into a
human readable structure and logs them using the logging service instantiated
within the class (in this case, a Cloud Logging client).
"""

import logging
import time

from google.cloud import logging
from grpc import UnaryUnaryClientInterceptor, UnaryStreamClientInterceptor

from google.ads.googleads.interceptors import LoggingInterceptor, mask_message


class CloudLoggingInterceptor(LoggingInterceptor):
    """An interceptor that logs rpc request and response details to Google Cloud Logging.

    This class inherits logic from the LoggingInterceptor, which simplifies the
    implementation here. Some logic is required here in order to make the
    underlying logic work -- comments make note of this where applicable.
    NOTE: Inheriting from the LoggingInterceptor class could yield unexpected side
    effects. For example, if the LoggingInterceptor class is updated, this class would
    inherit the updated logic, which could affect its functionality. One option to avoid
    this is to inherit from the Interceptor class instead, and selectively copy whatever
    logic is needed from the LoggingInterceptor class."""

    def __init__(self, api_version):
        """Initializer for the CloudLoggingInterceptor.

        Args:
            api_version: a str of the API version of the request.
        """
        super().__init__(logger=None, api_version=api_version)
        # Instantiate the Cloud Logging client.
        logging_client = logging.Client()
        self.logger = logging_client.logger("cloud_logging")

    def log_successful_request(
        self,
        method,
        customer_id,
        metadata_json,
        request_id,
        request,
        trailing_metadata_json,
        response,
    ):
        """Handles logging of a successful request.

        Args:
            method: The method of the request.
            customer_id: The customer ID associated with the request.
            metadata_json: A JSON str of initial_metadata.
            request_id: A unique ID for the request provided in the response.
            request: An instance of a request proto message.
            trailing_metadata_json: A JSON str of trailing_metadata.
            response: A grpc.Call/grpc.Future instance.
        """
        # Retrieve and mask the RPC result from the response future.
        # This method is available from the LoggingInterceptor class.
        # Ensure self._cache is set in order for this to work.
        # The response result could contain up to 10,000 rows of data,
        # so consider truncating this value before logging it, to save
        # on data storage costs and maintain readability.
        result = self.retrieve_and_mask_result(response)

        # elapsed_ms is the approximate elapsed time of the RPC, in milliseconds.
        # There are different ways to define and measure elapsed time, so use
        # whatever approach makes sense for your monitoring purposes.
        # rpc_start and rpc_end are set in the intercept_unary_* methods below.
        elapsed_ms = (self.rpc_end - self.rpc_start) * 1000

        debug_log = {
            "method": method,
            "host": metadata_json,
            "request_id": request_id,
            "request": str(request),
            "headers": trailing_metadata_json,
            "response": str(result),
            "is_fault": False,
            "elapsed_ms": elapsed_ms,
        }
        self.logger.log_struct(debug_log, severity="DEBUG")

        info_log = {
            "customer_id": customer_id,
            "method": method,
            "request_id": request_id,
            "is_fault": False,
            # Available from the Interceptor class.
            "api_version": self._api_version,
        }
        self.logger.log_struct(info_log, severity="INFO")

    def log_failed_request(
        self,
        method,
        customer_id,
        metadata_json,
        request_id,
        request,
        trailing_metadata_json,
        response,
    ):
        """Handles logging of a failed request.

        Args:
            method: The method of the request.
            customer_id: The customer ID associated with the request.
            metadata_json: A JSON str of initial_metadata.
            request_id: A unique ID for the request provided in the response.
            request: An instance of a request proto message.
            trailing_metadata_json: A JSON str of trailing_metadata.
            response: A JSON str of the response message.
        """
        exception = self._get_error_from_response(response)
        exception_str = self._parse_exception_to_str(exception)
        fault_message = self._get_fault_message(exception)

        info_log = {
            "method": method,
            "endpoint": self.endpoint,
            "host": metadata_json,
            "request_id": request_id,
            "request": str(request),
            "headers": trailing_metadata_json,
            "exception": exception_str,
            "is_fault": True,
        }
        self.logger.log_struct(info_log, severity="INFO")

        error_log = {
            "method": method,
            "endpoint": self.endpoint,
            "request_id": request_id,
            "customer_id": customer_id,
            "is_fault": True,
            "fault_message": fault_message,
        }
        self.logger.log_struct(error_log, severity="ERROR")

    def intercept_unary_unary(self, continuation, client_call_details, request):
        """Intercepts and logs API interactions.

        Overrides abstract method defined in grpc.UnaryUnaryClientInterceptor.

        Args:
            continuation: a function to continue the request process.
            client_call_details: a grpc._interceptor._ClientCallDetails
                instance containing request metadata.
            request: a SearchGoogleAdsRequest or SearchGoogleAdsStreamRequest
                message class instance.

        Returns:
            A grpc.Call/grpc.Future instance representing a service response.
        """
        # Set the rpc_end value to current time when RPC completes.
        def update_rpc_end(response_future):
            self.rpc_end = time.perf_counter()

        # Capture precise clock time to later calculate approximate elapsed
        # time of the RPC.
        self.rpc_start = time.perf_counter()

        # The below call is REQUIRED.
        response = continuation(client_call_details, request)

        response.add_done_callback(update_rpc_end)

        self.log_request(client_call_details, request, response)

        # The below return is REQUIRED.
        return response

    def intercept_unary_stream(
        self, continuation, client_call_details, request
    ):
        """Intercepts and logs API interactions for Unary-Stream requests.

        Overrides abstract method defined in grpc.UnaryStreamClientInterceptor.

        Args:
            continuation: a function to continue the request process.
            client_call_details: a grpc._interceptor._ClientCallDetails
                instance containing request metadata.
            request: a SearchGoogleAdsRequest or SearchGoogleAdsStreamRequest
                message class instance.

        Returns:
            A grpc.Call/grpc.Future instance representing a service response.
        """

        def on_rpc_complete(response_future):
            self.rpc_end = time.perf_counter()
            self.log_request(client_call_details, request, response_future)

        # Capture precise clock time to later calculate approximate elapsed
        # time of the RPC.
        self.rpc_start = time.perf_counter()

        # The below call is REQUIRED.
        response = continuation(client_call_details, request)

        # Set self._cache to the cache on the response wrapper in order to
        # access the streaming logs. This is REQUIRED in order to log streaming
        # requests.
        self._cache = response.get_cache()

        response.add_done_callback(on_rpc_complete)

        # The below return is REQUIRED.
        return response