علاقه مند به اشتراک گذاری بازخورد خود در مورد Google Ads API هستید؟ برای دعوت به شرکت در تحقیقات کاربر
ثبت نام کنید !
خطای کنترل نرخ بیش از حد
جاوا
// Copyright 2019 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.
package com.google.ads.googleads.examples.errorhandling;
import com.beust.jcommander.Parameter;
import com.google.ads.googleads.examples.utils.ArgumentNames;
import com.google.ads.googleads.examples.utils.CodeSampleParams;
import com.google.ads.googleads.lib.GoogleAdsClient;
import com.google.ads.googleads.v18.common.KeywordInfo;
import com.google.ads.googleads.v18.enums.AdGroupCriterionStatusEnum.AdGroupCriterionStatus;
import com.google.ads.googleads.v18.enums.KeywordMatchTypeEnum.KeywordMatchType;
import com.google.ads.googleads.v18.errors.GoogleAdsError;
import com.google.ads.googleads.v18.errors.GoogleAdsException;
import com.google.ads.googleads.v18.errors.QuotaErrorEnum.QuotaError;
import com.google.ads.googleads.v18.resources.AdGroupCriterion;
import com.google.ads.googleads.v18.services.AdGroupCriterionOperation;
import com.google.ads.googleads.v18.services.AdGroupCriterionServiceClient;
import com.google.ads.googleads.v18.services.MutateAdGroupCriteriaRequest;
import com.google.ads.googleads.v18.services.MutateAdGroupCriteriaResponse;
import com.google.ads.googleads.v18.utils.ResourceNames;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
/**
* Handles RateExceededError in an application. This code example runs 5 threads in parallel, each
* thread attempting to validate 100 keywords in a single request. While spanning 5 parallel threads
* is unlikely to trigger a rate exceeded error, substantially increasing the number of threads may
* have that effect. Note that this example is for illustrative purposes only, and you shouldn't
* intentionally try to trigger a rate exceed error in your application.
*/
public class HandleRateExceededError {
private static class HandleRateExceededErrorParams extends CodeSampleParams {
@Parameter(names = ArgumentNames.CUSTOMER_ID, required = true)
private Long customerId;
@Parameter(names = ArgumentNames.AD_GROUP_ID, required = true)
private Long adGroupId;
}
public static void main(String[] args) throws InterruptedException {
HandleRateExceededErrorParams params = new HandleRateExceededErrorParams();
if (!params.parseArguments(args)) {
// Either pass the required parameters for this example on the command line, or insert them
// into the code here. See the parameter class definition above for descriptions.
params.customerId = Long.parseLong("INSERT_CUSTOMER_ID_HERE");
params.adGroupId = Long.parseLong("INSERT_AD_GROUP_ID_HERE");
}
GoogleAdsClient googleAdsClient = null;
try {
googleAdsClient = GoogleAdsClient.newBuilder().fromPropertiesFile().build();
} catch (FileNotFoundException fnfe) {
System.err.printf(
"Failed to load GoogleAdsClient configuration from file. Exception: %s%n", fnfe);
System.exit(1);
} catch (IOException ioe) {
System.err.printf("Failed to create GoogleAdsClient. Exception: %s%n", ioe);
System.exit(1);
}
try {
new HandleRateExceededError()
.runExample(googleAdsClient, params.customerId, params.adGroupId);
} catch (GoogleAdsException gae) {
// GoogleAdsException is the base class for most exceptions thrown by an API request.
// Instances of this exception have a message and a GoogleAdsFailure that contains a
// collection of GoogleAdsErrors that indicate the underlying causes of the
// GoogleAdsException.
System.err.printf(
"Request ID %s failed due to GoogleAdsException. Underlying errors:%n",
gae.getRequestId());
int i = 0;
for (GoogleAdsError googleAdsError : gae.getGoogleAdsFailure().getErrorsList()) {
System.err.printf(" Error %d: %s%n", i++, googleAdsError);
}
System.exit(1);
}
}
/**
* Runs the example.
*
* @param googleAdsClient the Google Ads API client.
* @param customerId the client customer ID.
* @param adGroupId the ID of the ad group to which keywords are added.
*/
private void runExample(GoogleAdsClient googleAdsClient, long customerId, long adGroupId)
throws InterruptedException {
final int NUM_THREADS = 5;
List<Thread> threads = new ArrayList<>();
// Adds 5 threads that validate keywords to a list.
for (int i = 0; i < NUM_THREADS; i++) {
KeywordsThread keywordsThread = new KeywordsThread(googleAdsClient, customerId, adGroupId, i);
Thread thread = new Thread(keywordsThread);
threads.add(thread);
}
// Starts the threads.
for (Thread thread : threads) {
thread.start();
}
// Ensures the calling thread waits until all threads of terminated.
for (Thread thread : threads) {
thread.join();
}
}
/** Thread class for validating keywords */
private static class KeywordsThread implements Runnable {
// Number of keywords to be validated in each API call.
private final int NUM_KEYWORDS = 100;
// The GoogleAdsClient.
private final GoogleAdsClient googleAdsClient;
// The customer ID.
private final long customerId;
// The ad group ID to which keywords are added.
private final long adGroupId;
// Index of this thread, for identifying and debugging.
private final int threadIndex;
/**
* Initializes a new instance of the KeywordThread
*
* @param googleAdsClient the Google Ads API client.
* @param customerId the client customer ID.
* @param adGroupId the ID of the ad group to which keywords are added.
* @param threadIndex the index of the thread.
*/
public KeywordsThread(
GoogleAdsClient googleAdsClient, long customerId, long adGroupId, int threadIndex) {
this.googleAdsClient = googleAdsClient;
this.customerId = customerId;
this.adGroupId = adGroupId;
this.threadIndex = threadIndex;
}
/** Main method for the thread. */
public void run() {
List<AdGroupCriterionOperation> operations = new ArrayList<>();
for (int i = 0; i < NUM_KEYWORDS; i++) {
// Configures the keywordText text and match type settings.
KeywordInfo keywordInfo =
KeywordInfo.newBuilder()
.setText(
"mars cruise thread "
+ String.valueOf(threadIndex)
+ " seed "
+ ""
+ String.valueOf(i))
.setMatchType(KeywordMatchType.EXACT)
.build();
String adGroupResourceName = ResourceNames.adGroup(customerId, adGroupId);
// Constructs an ad group criterion using the keywordText configuration above.
AdGroupCriterion criterion =
AdGroupCriterion.newBuilder()
.setAdGroup(adGroupResourceName)
.setStatus(AdGroupCriterionStatus.PAUSED)
.setKeyword(keywordInfo)
.build();
// Creates the operation.
AdGroupCriterionOperation operation =
AdGroupCriterionOperation.newBuilder().setCreate(criterion).build();
operations.add(operation);
}
// Gets the AdGroupCriterionService. This should be done within the thread, since a service
// can only handle one outgoing HTTP request at a time.
try (AdGroupCriterionServiceClient adGroupCriterionServiceClient =
googleAdsClient.getLatestVersion().createAdGroupCriterionServiceClient()) {
int retryCount = 0;
int retrySeconds = 10;
final int NUM_RETRIES = 3;
try {
while (retryCount < NUM_RETRIES) {
try {
// Creates the validateOnly request.
MutateAdGroupCriteriaRequest mutateAdGroupCriteriaRequest =
MutateAdGroupCriteriaRequest.newBuilder()
.setCustomerId(Long.toString(customerId))
.addAllOperations(operations)
.setValidateOnly(true)
.build();
// Makes the mutate request. The result set will be empty because validateOnly is set
// to true in the MutateAdGroupCriteriaRequest.
MutateAdGroupCriteriaResponse response =
adGroupCriterionServiceClient.mutateAdGroupCriteria(mutateAdGroupCriteriaRequest);
System.out.printf("%d operations validated.%n", operations.size());
break;
} catch (GoogleAdsException gae) {
for (GoogleAdsError googleAdsError : gae.getGoogleAdsFailure().getErrorsList()) {
// Checks if any of the errors are QuotaError.RESOURCE_EXHAUSTED or
// QuotaError.RESOURCE_TEMPORARILY_EXHAUSTED.
if (googleAdsError.getErrorCode().getQuotaError() == QuotaError.RESOURCE_EXHAUSTED
|| googleAdsError.getErrorCode().getQuotaError()
== QuotaError.RESOURCE_TEMPORARILY_EXHAUSTED) {
System.err.printf(
"Received rate exceeded error, retry after %d seconds.%n", retrySeconds);
Thread.sleep(retrySeconds * 1000);
retryCount++;
// Uses an exponential backoff policy to avoid polling too aggressively.
retrySeconds *= 2;
}
}
} finally {
if (retryCount == NUM_RETRIES) {
throw new Exception(
String.format("Could not recover after making %d attempts.%n", retryCount));
}
}
}
} catch (Exception e) {
System.err.printf("Failed to validate keywords.%n", e);
System.exit(1);
}
}
}
}
}
سی شارپ
// Copyright 2020 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
//
// http://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.
using CommandLine;
using Google.Ads.Gax.Examples;
using Google.Ads.GoogleAds.Lib;
using Google.Ads.GoogleAds.V18.Common;
using Google.Ads.GoogleAds.V18.Errors;
using Google.Ads.GoogleAds.V18.Resources;
using Google.Ads.GoogleAds.V18.Services;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using static Google.Ads.GoogleAds.V18.Enums.AdGroupCriterionStatusEnum.Types;
using static Google.Ads.GoogleAds.V18.Enums.KeywordMatchTypeEnum.Types;
using static Google.Ads.GoogleAds.V18.Errors.QuotaErrorEnum.Types;
namespace Google.Ads.GoogleAds.Examples.V18
{
/// <summary>
/// This code example demonstrates how to handle RateExceededError in an application.
/// This code example runs 5 threads in parallel, each thread attempting to validate
/// 100 keywords in a single request. While spanning 5 parallel threads is unlikely to
/// trigger a rate exceeded error, substantially increasing the number of threads may
/// have that effect. Note that this example is for illustrative purposes only, and you
/// shouldn't intentionally try to trigger a rate exceed error in your application.
/// </summary>
public class HandleRateExceededError : ExampleBase
{
/// <summary>
/// Command line options for running the <see cref="HandleRateExceededError"/> example.
/// </summary>
public class Options : OptionsBase
{
/// <summary>
/// The customer ID for which the call is made.
/// </summary>
[Option("customerId", Required = true, HelpText =
"The customer ID for which the call is made.")]
public long CustomerId { get; set; }
/// <summary>
/// ID of the ad group to which keywords are added.
/// </summary>
[Option("adGroupId", Required = true, HelpText =
"ID of the ad group to which keywords are added.")]
public long AdGroupId { get; set; }
}
/// <summary>
/// Main method, to run this code example as a standalone application.
/// </summary>
/// <param name="args">The command line arguments.</param>
public static void Main(string[] args)
{
Options options = ExampleUtilities.ParseCommandLine<Options>(args);
HandleRateExceededError codeExample = new HandleRateExceededError();
Console.WriteLine(codeExample.Description);
codeExample.Run(new GoogleAdsClient(), options.CustomerId, options.AdGroupId);
}
// Number of threads to use in the code example.
private const int NUM_THREADS = 5;
// Number of keywords to be validated in each API call.
private const int NUM_KEYWORDS = 5000;
/// <summary>
/// Returns a description about the code example.
/// </summary>
public override string Description =>
"This code example demonstrates how to handle RateExceededError in an application. " +
"This code example runs 5 threads in parallel, each thread attempting to validate " +
"100 keywords in a single request. While spanning 5 parallel threads is unlikely to " +
"trigger a rate exceeded error, substantially increasing the number of threads may " +
"have that effect. Note that this example is for illustrative purposes only, and you " +
"shouldn't intentionally try to trigger a rate exceed error in your application.";
/// <summary>
/// Runs the code example.
/// </summary>
/// <param name="client">The Google Ads client.</param>
/// <param name="customerId">The customer ID for which the call is made.</param>
/// <param name="adGroupId">ID of the ad group to which keywords are added.</param>
public void Run(GoogleAdsClient client, long customerId, long adGroupId)
{
List<Task> tasks = new List<Task>();
for (int i = 0; i < NUM_THREADS; i++)
{
Task t = CreateKeyword(client, i, customerId, adGroupId);
tasks.Add(t);
}
Task.WaitAll(tasks.ToArray());
}
/// <summary>
/// Displays the result from the mutate operation.
/// </summary>
/// <param name="client">The Google Ads client.</param>
/// <param name="customerId">The Google Ads customer ID for which the call is made.</param>
/// <param name="adGroupId">The ad group to which keywords are added.</param>
/// <param name="threadIndex">The thread ID.</param>
private async Task CreateKeyword(GoogleAdsClient client, int threadIndex, long customerId,
long adGroupId)
{
await Task.Run(() =>
{
// Get the AdGroupCriterionServiceClient.
AdGroupCriterionServiceClient adGroupCriterionService =
client.GetService(Services.V18.AdGroupCriterionService);
List<AdGroupCriterionOperation> operations = new List<AdGroupCriterionOperation>();
for (int i = 0; i < NUM_KEYWORDS; i++)
{
AdGroupCriterion criterion = new AdGroupCriterion()
{
Keyword = new KeywordInfo()
{
Text = $"mars cruise thread {threadIndex} seed {i}",
MatchType = KeywordMatchType.Exact
},
AdGroup = ResourceNames.AdGroup(customerId, adGroupId),
Status = AdGroupCriterionStatus.Paused
};
// Creates the operation.
operations.Add(new AdGroupCriterionOperation() { Create = criterion });
}
int retryCount = 0;
int retrySeconds = 30;
const int NUM_RETRIES = 3;
while (retryCount < NUM_RETRIES)
{
try
{
// Makes the validateOnly mutate request.
MutateAdGroupCriteriaResponse response =
adGroupCriterionService.MutateAdGroupCriteria(
new MutateAdGroupCriteriaRequest()
{
CustomerId = customerId.ToString(),
Operations = { operations },
PartialFailure = false,
ValidateOnly = true
});
Console.WriteLine($"[{threadIndex}] Validated {operations.Count} " +
$"ad group criteria:");
break;
}
catch (GoogleAdsException e)
{
// Checks if any of the errors are QuotaError.RESOURCE_EXHAUSTED or
// QuotaError.RESOURCE_TEMPORARILY_EXHAUSTED.
// Note: The code assumes that the developer token is approved for
// Standard Access.
if (e.Failure != null)
{
bool isRateExceededError = false;
e.Failure.Errors
.Where(err =>
err.ErrorCode.QuotaError == QuotaError.ResourceExhausted ||
err.ErrorCode.QuotaError == QuotaError.ResourceTemporarilyExhausted)
.ToList()
.ForEach(delegate (GoogleAdsError err)
{
Console.Error.WriteLine($"[{threadIndex}] Received rate " +
$"exceeded error. Message says, \"{err.Message}\".");
isRateExceededError = true;
}
);
if (isRateExceededError)
{
Console.Error.WriteLine(
$"[{threadIndex}] Will retry after {retrySeconds} seconds.");
Thread.Sleep(retrySeconds * 1000);
retryCount++;
// Uses an exponential backoff policy to avoid polling too
// aggressively.
retrySeconds *= 2;
}
}
else
{
Console.WriteLine("Failure:");
Console.WriteLine($"Message: {e.Message}");
Console.WriteLine($"Failure: {e.Failure}");
Console.WriteLine($"Request ID: {e.RequestId}");
break;
}
}
finally
{
if (retryCount == NUM_RETRIES)
{
throw new Exception($"[{ threadIndex }] Could not recover after " +
$"making {retryCount} attempts.");
}
}
}
});
}
}
}
PHP
<?php
/**
* Copyright 2019 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.
*/
namespace Google\Ads\GoogleAds\Examples\ErrorHandling;
require __DIR__ . '/../../vendor/autoload.php';
use GetOpt\GetOpt;
use Google\Ads\GoogleAds\Examples\Utils\ArgumentNames;
use Google\Ads\GoogleAds\Examples\Utils\ArgumentParser;
use Google\Ads\GoogleAds\Lib\OAuth2TokenBuilder;
use Google\Ads\GoogleAds\Lib\V18\GoogleAdsClient;
use Google\Ads\GoogleAds\Lib\V18\GoogleAdsClientBuilder;
use Google\Ads\GoogleAds\Lib\V18\GoogleAdsException;
use Google\Ads\GoogleAds\Util\V18\ResourceNames;
use Google\Ads\GoogleAds\V18\Common\KeywordInfo;
use Google\Ads\GoogleAds\V18\Enums\AdGroupCriterionStatusEnum\AdGroupCriterionStatus;
use Google\Ads\GoogleAds\V18\Enums\KeywordMatchTypeEnum\KeywordMatchType;
use Google\Ads\GoogleAds\V18\Errors\GoogleAdsError;
use Google\Ads\GoogleAds\V18\Errors\QuotaErrorEnum\QuotaError;
use Google\Ads\GoogleAds\V18\Resources\AdGroupCriterion;
use Google\Ads\GoogleAds\V18\Services\AdGroupCriterionOperation;
use Google\Ads\GoogleAds\V18\Services\GoogleAdsRow;
use Google\Ads\GoogleAds\V18\Services\MutateAdGroupCriteriaRequest;
use Google\ApiCore\ApiException;
use Exception;
/**
* Handles RateExceededError in an application. This code example runs 5 requests sequentially,
* each request attempting to validate 100 keywords. While it is unlikely that running
* these requests would trigger a rate exceeded error, substantially increasing the
* number of requests may have that effect. Note that this example is for illustrative
* purposes only, and you shouldn't intentionally try to trigger a rate exceed error in your
* application.
*/
class HandleRateExceededError
{
private const CUSTOMER_ID = 'INSERT_CUSTOMER_ID_HERE';
private const AD_GROUP_ID = 'INSERT_AD_GROUP_ID_HERE';
// Number of requests to be run.
private const NUM_REQUESTS = 5;
// Number of keywords to be validated in each API call.
private const NUM_KEYWORDS = 100;
// Number of retries to be run in case of a RateExceededError.
private const NUM_RETRIES = 3;
// Minimum number of seconds to wait before a retry.
private const RETRY_SECONDS = 10;
public static function main()
{
// Either pass the required parameters for this example on the command line, or insert them
// into the constants above.
$options = (new ArgumentParser())->parseCommandArguments([
ArgumentNames::CUSTOMER_ID => GetOpt::REQUIRED_ARGUMENT,
ArgumentNames::AD_GROUP_ID => GetOpt::REQUIRED_ARGUMENT
]);
// Generate a refreshable OAuth2 credential for authentication.
$oAuth2Credential = (new OAuth2TokenBuilder())->fromFile()->build();
// Construct a Google Ads client configured from a properties file and the
// OAuth2 credentials above.
$googleAdsClient = (new GoogleAdsClientBuilder())->fromFile()
->withOAuth2Credential($oAuth2Credential)
->build();
try {
self::runExample(
$googleAdsClient,
$options[ArgumentNames::CUSTOMER_ID] ?: self::CUSTOMER_ID,
$options[ArgumentNames::AD_GROUP_ID] ?: self::AD_GROUP_ID
);
} catch (GoogleAdsException $googleAdsException) {
printf(
"Request with ID '%s' has failed.%sGoogle Ads failure details:%s",
$googleAdsException->getRequestId(),
PHP_EOL,
PHP_EOL
);
foreach ($googleAdsException->getGoogleAdsFailure()->getErrors() as $error) {
/** @var GoogleAdsError $error */
printf(
"\t%s: %s%s",
$error->getErrorCode()->getErrorCode(),
$error->getMessage(),
PHP_EOL
);
}
exit(1);
} catch (ApiException $apiException) {
printf(
"ApiException was thrown with message '%s'.%s",
$apiException->getMessage(),
PHP_EOL
);
exit(1);
}
}
/**
* Runs the example.
*
* @param GoogleAdsClient $googleAdsClient the Google Ads API client
* @param int $customerId the customer ID
* @param int $adGroupId the ad group ID to validate keywords from
*/
public static function runExample(
GoogleAdsClient $googleAdsClient,
int $customerId,
int $adGroupId
) {
// Sequentially sends the requests.
for ($i = 0; $i < self::NUM_REQUESTS; $i++) {
// Creates operations.
$operations = self::createAdGroupCriterionOperations($customerId, $adGroupId, $i);
try {
$retryCount = 0;
$retrySeconds = self::RETRY_SECONDS;
while ($retryCount < self::NUM_RETRIES) {
try {
// Sends request.
self::requestMutateAndDisplayResult(
$googleAdsClient,
$customerId,
$operations
);
break;
} catch (GoogleAdsException $googleAdsException) {
$hasRateExceededError = false;
foreach (
$googleAdsException->getGoogleAdsFailure()
->getErrors() as $googleAdsError
) {
// Checks if any of the errors are QuotaError.RESOURCE_EXHAUSTED or
// QuotaError.RESOURCE_TEMPORARILY_EXHAUSTED.
if (
$googleAdsError->getErrorCode()->getQuotaError()
== QuotaError::RESOURCE_EXHAUSTED
|| $googleAdsError->getErrorCode()->getQuotaError()
== QuotaError::RESOURCE_TEMPORARILY_EXHAUSTED
) {
printf(
'Received rate exceeded error, retry after %d seconds.%s',
$retrySeconds,
PHP_EOL
);
sleep($retrySeconds);
$hasRateExceededError = true;
$retryCount++;
// Uses an exponential back-off policy.
$retrySeconds *= 2;
break;
}
}
// Bubbles up when there is not RateExceededError
if (!$hasRateExceededError) {
throw $googleAdsException;
}
} finally {
// Bubbles up when the number of retries has already been reached.
if ($retryCount == self::NUM_RETRIES) {
throw new Exception(sprintf(
'Could not recover after making %d attempts.%s',
$retryCount,
PHP_EOL
));
}
}
}
} catch (Exception $exception) {
// Prints any unhandled exception and bubbles up.
printf(
'Failed to validate keywords.%1$s%2$s%1$s',
PHP_EOL,
$exception->getMessage()
);
throw $exception;
}
}
}
/**
* Creates ad group criterion operations.
*
* @param int $customerId the customer ID
* @param int $adGroupId the ad group ID to link the ad group criteria to
* @param int $reqIndex the request index
* @return array the created ad group criterion operations
*/
private static function createAdGroupCriterionOperations(
int $customerId,
int $adGroupId,
int $reqIndex
) {
$operations = [];
for ($i = 0; $i < self::NUM_KEYWORDS; $i++) {
// Creates a keyword info.
$keywordInfo = new KeywordInfo([
'text' => 'mars cruise req ' . $reqIndex . ' seed ' . $i,
'match_type' => KeywordMatchType::EXACT
]);
// Constructs an ad group criterion using the keyword text info above.
$adGroupCriterion = new AdGroupCriterion([
'ad_group' => ResourceNames::forAdGroup($customerId, $adGroupId),
'status' => AdGroupCriterionStatus::ENABLED,
'keyword' => $keywordInfo
]);
// Creates an ad group criterion operation.
$adGroupCriterionOperation = new AdGroupCriterionOperation();
$adGroupCriterionOperation->setCreate($adGroupCriterion);
$operations[] = $adGroupCriterionOperation;
}
return $operations;
}
/**
* Requests a mutate of ad group criterion operations and displays the results.
*
* @param GoogleAdsClient $googleAdsClient the Google Ads API client
* @param int $customerId the customer ID
* @param array $operations the ad group criterion operations
*/
private static function requestMutateAndDisplayResult(
GoogleAdsClient $googleAdsClient,
int $customerId,
array $operations
) {
$adGroupCriterionServiceClient = $googleAdsClient->getAdGroupCriterionServiceClient();
// Makes a validateOnly mutate request.
$response = $adGroupCriterionServiceClient->mutateAdGroupCriteria(
MutateAdGroupCriteriaRequest::build($customerId, $operations)
->setPartialFailure(false)
->setValidateOnly(true)
);
// Displays the results.
printf(
"Added %d ad group criteria:%s",
$response->getResults()->count(),
PHP_EOL
);
foreach ($response->getResults() as $result) {
/** @var GoogleAdsRow $result */
print $result->getAdGroupCriterion()->getResourceName() . PHP_EOL;
}
}
}
HandleRateExceededError::main();
پایتون
#!/usr/bin/env python
# Copyright 2020 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.
"""Handles RateExceededError in an application.
This code example runs 5 requests sequentially, each request attempting to
validate 100 keywords. While it is unlikely that running these requests would
trigger a rate exceeded error, substantially increasing the number of requests
may have that effect. Note that this example is for illustrative purposes only,
and you shouldn't intentionally try to trigger a rate exceed error in your
application.
"""
import argparse
from time import sleep
from google.ads.googleads.client import GoogleAdsClient
from google.ads.googleads.errors import GoogleAdsException
# Number of requests to be run.
NUM_REQUESTS = 5
# Number of keywords to be validated in each API call.
NUM_KEYWORDS = 100
# Number of retries to be run in case of a RateExceededError.
NUM_RETRIES = 3
# Minimum number of seconds to wait before a retry.
RETRY_SECONDS = 10
def main(client, customer_id, ad_group_id):
"""Runs the example code, which shows how to handle rate exceeded errors.
Args:
client: An initialized GoogleAdsClient instance.
customer_id: A valid customer account ID.
ad_group_id: The ad group ID to validate keywords from.
"""
quota_error_enum = client.get_type("QuotaErrorEnum").QuotaError
resource_exhausted = quota_error_enum.RESOURCE_EXHAUSTED
temp_resource_exhausted = quota_error_enum.RESOURCE_TEMPORARILY_EXHAUSTED
for i in range(NUM_REQUESTS):
operations = create_ad_group_criterion_operations(
client, customer_id, ad_group_id, i
)
try:
retry_count = 0
retry_seconds = RETRY_SECONDS
while retry_count < NUM_RETRIES:
try:
request_mutate_and_display_result(
client, customer_id, operations
)
break
except GoogleAdsException as ex:
has_rate_exceeded_error = False
for googleads_error in ex.failure.errors:
# Checks if any of the errors are
# QuotaError.RESOURCE_EXHAUSTED or
# QuotaError.RESOURCE_TEMPORARILY_EXHAUSTED.
quota_error = googleads_error.error_code.quota_error
if (
quota_error == resource_exhausted
or quota_error == temp_resource_exhausted
):
print(
"Received rate exceeded error, retry after"
f"{retry_seconds} seconds."
)
sleep(retry_seconds)
has_rate_exceeded_error = True
retry_count += 1
# Here exponential backoff is employed to ensure
# the account doesn't get rate limited by making
# too many requests too quickly. This increases the
# time to wait between requests by a factor of 2.
retry_seconds *= 2
break
# Bubbles up when there is not a RateExceededError
if not has_rate_exceeded_error:
raise ex
finally:
if retry_count == NUM_RETRIES:
raise Exception(
"Could not recover after making "
f"{retry_count} attempts."
)
except Exception as ex:
# Prints any unhandled exception and bubbles up.
print(f"Failed to validate keywords: {ex}")
raise ex
def create_ad_group_criterion_operations(
client, customer_id, ad_group_id, request_index
):
"""Creates ad group criterion operations.
The number of operations created depends on the number of keywords this
example should remove. That value is configurable via the NUM_KEYWORDS
variable.
Args:
client: An initialized GoogleAdsClient instance.
customer_id: A valid customer account ID.
ad_group_id: An ID for an AdGroup.
request_index: The number from a sequence of requests in which these
operations will be sent.
Returns:
A list of AdGroupCriterionOperation instances.
"""
ad_group_service = client.get_service("AdGroupService")
status = client.enums.AdGroupCriterionStatusEnum.ENABLED
match_type = client.enums.KeywordMatchTypeEnum.EXACT
operations = []
for i in range(NUM_KEYWORDS):
ad_group_criterion_operation = client.get_type(
"AdGroupCriterionOperation"
)
ad_group_criterion = ad_group_criterion_operation.create
ad_group_criterion.ad_group = ad_group_service.ad_group_path(
customer_id, ad_group_id
)
ad_group_criterion.status = status
ad_group_criterion.keyword.text = (
f"mars cruise req {request_index} seed {i}"
)
ad_group_criterion.keyword.match_type = match_type
operations.append(ad_group_criterion_operation)
return operations
def request_mutate_and_display_result(client, customer_id, operations):
"""Mutates a set of ad group criteria as a dry-run and displays the results.
The request is sent with validate_only set to true, so no actual mutations
will be made in the API.
Args:
client: An initialized GoogleAdsClient instance.
customer_id: A valid customer account ID.
operations: a list of AdGroupCriterionOperation instances.
"""
ad_group_criterion_service = client.get_service("AdGroupCriterionService")
request = client.get_type("MutateAdGroupCriteriaRequest")
request.customer_id = customer_id
request.operations = operations
request.validate_only = True
response = ad_group_criterion_service.mutate_ad_group_criteria(
request=request
)
print(f"Added {len(response.results)} ad group criteria:")
for ad_group_criterion in response.results:
print(f"Resource name: '{ad_group_criterion.resource_name}'")
if __name__ == "__main__":
parser = argparse.ArgumentParser(
description="Handles RateExceededError in an application.."
)
# The following argument(s) should be provided to run the example.
parser.add_argument(
"-c",
"--customer_id",
type=str,
required=True,
help="The Google Ads customer ID.",
)
parser.add_argument(
"-a",
"--ad_group_id",
type=str,
required=True,
help="The ID of an ad group belonging to the given customer.",
)
args = parser.parse_args()
# GoogleAdsClient will read the google-ads.yaml configuration file in the
# home directory if none is specified.
googleads_client = GoogleAdsClient.load_from_storage(version="v18")
main(googleads_client, args.customer_id, args.ad_group_id)
روبی
# Encoding: utf-8
#
# Copyright 2020 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.
#
# Handles RateExceededError in an application. This code example runs 5 requests
# sequentially, each request attempting to validate 100 keywords. While it is
# unlikely that running these requests would trigger a rate exceeded error,
# substantially increasing the number of requests may have that effect. Note
# that this example is for illustrative purposes only, and you shouldn't
# intentionally try to trigger a rate exceed error in your application.
require 'optparse'
require 'google/ads/google_ads'
require 'date'
def handle_rate_exceeded_error(customer_id, ad_group_id)
# GoogleAdsClient will read a config file from
# ENV['HOME']/google_ads_config.rb when called without parameters
client = Google::Ads::GoogleAds::GoogleAdsClient.new
# Sequentially sends the requests.
NUM_REQUESTS.times do |i|
# Creates operations.
operations = create_ad_group_criterion_operations(
client, customer_id, ad_group_id, i)
begin
retry_count = 0
retry_seconds = RETRY_SECONDS
while retry_count < NUM_RETRIES
begin
# Sends request.
request_mutate_and_display_result(client, customer_id, operations)
break
rescue Google::Ads::GoogleAds::Errors::GoogleAdsError => e
has_rate_exceeded_error = false
e.failure.errors.each do |error|
# Checks if any of the errors are QuotaError.RESOURCE_EXHAUSTED or
# QuotaError.RESOURCE_TEMPORARILY_EXHAUSTED.
if error.error_code.quota_error == :RESOURCE_EXHAUSTED \
|| error.error_code.quota_error == :RESOURCE_TEMPORARILY_EXHAUSTED
puts "Received rate exceeded error, retry after " \
"#{retry_seconds} seconds."
sleep retry_seconds
has_rate_exceeded_error = true
retry_count += 1
# Uses an exponential back-off policy.
retry_seconds *= 2
break
end
end
# Bubbles up when there is not RateExceededError.
if !has_rate_exceeded_error
raise
end
ensure
# Bubbles up when the number of retries has already been reached.
if retry_count == NUM_RETRIES
raise "Could not recover after making #{retry_count} attempts."
end
end
end
rescue StandardError => e
# Prints any unhandled exception and bubbles up.
puts "Failed to validate keywords. #{e.message}"
raise
end
end
end
def create_ad_group_criterion_operations(
client,
customer_id,
ad_group_id,
req_index
)
operations = []
NUM_KEYWORDS.times do |i|
# Creates an ad group criterion operation.
operations << client.operation.create_resource.ad_group_criterion do |agc|
agc.ad_group = client.path.ad_group(customer_id, ad_group_id)
agc.status = :ENABLED
agc.keyword = client.resource.keyword_info do |ki|
ki.text = "mars cruise req #{req_index} seed #{i}"
ki.match_type = :EXACT
end
end
end
operations
end
def request_mutate_and_display_result(client, customer_id, operations)
# Makes a validate_only mutate request.
response = client.service.ad_group_criterion.mutate_ad_group_criteria(
customer_id: customer_id,
operations: operations,
partial_failure: false,
validate_only: true,
)
# Displays the results.
puts "Added #{response.results.size} ad group criteria:"
response.results.each do |result|
puts "\t#{result.resource_name}"
end
end
if __FILE__ == $PROGRAM_NAME
# Number of requests to be run.
NUM_REQUESTS = 5
# Number of keywords to be validated in each API call.
NUM_KEYWORDS = 100
# Number of retries to be run in case of a RateExceededError.
NUM_RETRIES = 3
# Minimum number of seconds to wait before a retry.
RETRY_SECONDS = 10
options = {}
# The following parameter(s) should be provided to run the example. You can
# either specify these by changing the INSERT_XXX_ID_HERE values below, or on
# the command line.
#
# Parameters passed on the command line will override any parameters set in
# code.
#
# Running the example with -h will print the command line usage.
options[:customer_id] = 'INSERT_CUSTOMER_ID_HERE'
options[:ad_group_id] = 'INSERT_AD_GROUP_ID_HERE'
OptionParser.new do |opts|
opts.banner = sprintf('Usage: ruby %s [options]', File.basename(__FILE__))
opts.separator ''
opts.separator 'Options:'
opts.on('-C', '--customer-id CUSTOMER-ID', String, 'Customer ID') do |v|
options[:customer_id] = v
end
opts.on('-A', '--ad-group-id AD-GROUP-ID', String, 'Ad Group ID') do |v|
options[:ad_group_id] = v
end
opts.separator ''
opts.separator 'Help:'
opts.on_tail('-h', '--help', 'Show this message') do
puts opts
exit
end
end.parse!
begin
handle_rate_exceeded_error(
options.fetch(:customer_id).tr("-", ""),
options.fetch(:ad_group_id),
)
rescue Google::Ads::GoogleAds::Errors::GoogleAdsError => e
e.failure.errors.each do |error|
STDERR.printf("Error with message: %s\n", error.message)
if error.location
error.location.field_path_elements.each do |field_path_element|
STDERR.printf("\tOn field: %s\n", field_path_element.field_name)
end
end
error.error_code.to_h.each do |k, v|
next if v == :UNSPECIFIED
STDERR.printf("\tType: %s\n\tCode: %s\n", k, v)
end
end
raise
end
end
پرل
#!/usr/bin/perl -w
#
# Copyright 2019, 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
#
# http://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.
#
# Handles RateExceededError in an application. This code example runs 5 requests
# sequentially, each request attempting to validate 100 keywords. While it is
# unlikely that running these requests would trigger a rate exceeded error,
# substantially increasing the number of requests may have that effect. Note that
# this example is for illustrative purposes only, and you shouldn't intentionally
# try to trigger a rate exceed error in your application.
use strict;
use warnings;
use utf8;
use FindBin qw($Bin);
use lib "$Bin/../../lib";
use Google::Ads::GoogleAds::Client;
use Google::Ads::GoogleAds::Utils::GoogleAdsHelper;
use Google::Ads::GoogleAds::V18::Resources::AdGroupCriterion;
use Google::Ads::GoogleAds::V18::Common::KeywordInfo;
use Google::Ads::GoogleAds::V18::Enums::KeywordMatchTypeEnum qw(EXACT);
use Google::Ads::GoogleAds::V18::Enums::AdGroupCriterionStatusEnum qw(ENABLED);
use
Google::Ads::GoogleAds::V18::Services::AdGroupCriterionService::AdGroupCriterionOperation;
use Google::Ads::GoogleAds::V18::Utils::ResourceNames;
use Getopt::Long qw(:config auto_help);
use Pod::Usage;
use Cwd qw(abs_path);
use Time::HiRes qw(sleep);
# Number of requests to be run.
use constant NUM_REQUESTS => 5;
# Number of keywords to be validated in each API call.
use constant NUM_KEYWORDS => 100;
# Number of retries to be run in case of a RateExceededError.
use constant NUM_RETRIES => 3;
# Minimum number of seconds to wait before a retry.
use constant RETRY_SECONDS => 10;
# The following parameter(s) should be provided to run the example. You can
# either specify these by changing the INSERT_XXX_ID_HERE values below, or on
# the command line.
#
# Parameters passed on the command line will override any parameters set in
# code.
#
# Running the example with -h will print the command line usage.
my $customer_id = "INSERT_CUSTOMER_ID_HERE";
my $ad_group_id = "INSERT_AD_GROUP_ID_HERE";
sub handle_rate_exceeded_error {
my ($api_client, $customer_id, $ad_group_id) = @_;
# Sequentially send the requests.
for (my $i = 0 ; $i < NUM_REQUESTS ; $i++) {
# Create operations.
my $operations =
create_ad_group_criterion_operations($customer_id, $ad_group_id, $i);
eval {
my $retry_count = 0;
my $retry_seconds = RETRY_SECONDS;
while ($retry_count < NUM_RETRIES) {
# Send request.
my $response =
request_mutate_and_display_result($api_client, $customer_id,
$operations);
if ($response->isa("Google::Ads::GoogleAds::GoogleAdsException")) {
my $has_rate_exceeded_error = 0;
foreach my $error (@{$response->get_google_ads_failure()->{errors}}) {
# Check if any of the errors are QuotaError.RESOURCE_EXHAUSTED or
# QuotaError.RESOURCE_TEMPORARILY_EXHAUSTED.
my $quota_error = $error->{errorCode}{quotaError};
if ($quota_error && grep /^$quota_error/,
("RESOURCE_EXHAUSTED", "RESOURCE_TEMPORARILY_EXHAUSTED"))
{
printf "Received rate exceeded error, retry after %d seconds.\n",
$retry_seconds;
sleep($retry_seconds);
$has_rate_exceeded_error = 1;
$retry_count++;
# Use an exponential back-off policy.
$retry_seconds *= 2;
last;
}
}
# Bubble up when there is not RateExceededError.
if (not $has_rate_exceeded_error) {
die $response->get_message();
}
} else {
last;
}
# Bubble up when the number of retries has already been reached.
if ($retry_count == NUM_RETRIES) {
die "Could not recover after making $retry_count attempts.\n",;
}
}
};
if ($@) {
# Catch and print any unhandled exception.
printf "Failed to validate keywords.\n%s", $@;
return 0;
}
}
return 1;
}
# Creates ad group criterion operations.
sub create_ad_group_criterion_operations {
my ($customer_id, $ad_group_id, $request_index) = @_;
my $operations = [];
for (my $i = 0 ; $i < NUM_KEYWORDS ; $i++) {
# Create a keyword info.
my $keyword_info = Google::Ads::GoogleAds::V18::Common::KeywordInfo->new({
text => "mars cruise req " . $request_index . " seed " . $i,
matchType => EXACT
});
# Construct an ad group criterion using the keyword text info above.
my $ad_group_criterion =
Google::Ads::GoogleAds::V18::Resources::AdGroupCriterion->new({
adGroup => Google::Ads::GoogleAds::V18::Utils::ResourceNames::ad_group(
$customer_id, $ad_group_id
),
status => ENABLED,
keyword => $keyword_info
});
# Create an ad group criterion operation.
my $ad_group_criterion_operation =
Google::Ads::GoogleAds::V18::Services::AdGroupCriterionService::AdGroupCriterionOperation
->new({
create => $ad_group_criterion
});
push @$operations, $ad_group_criterion_operation;
}
return $operations;
}
# Requests a mutate of ad group criterion operations and displays the results.
sub request_mutate_and_display_result {
my ($api_client, $customer_id, $operations) = @_;
# Make a validateOnly mutate request.
my $ad_group_criteria_response =
$api_client->AdGroupCriterionService()->mutate({
customerId => $customer_id,
operations => $operations,
partialFailure => "false",
validateOnly => "true"
});
# Display the results.
if (
not $ad_group_criteria_response->isa(
"Google::Ads::GoogleAds::GoogleAdsException"))
{
my $ad_group_criterion_results = $ad_group_criteria_response->{results};
printf "Added %d ad group criteria:\n", scalar @$ad_group_criterion_results;
foreach my $ad_group_criterion_result (@$ad_group_criterion_results) {
print $ad_group_criterion_result->{resourceName}, "\n";
}
}
return $ad_group_criteria_response;
}
# Don't run the example if the file is being included.
if (abs_path($0) ne abs_path(__FILE__)) {
return 1;
}
# Get Google Ads Client, credentials will be read from ~/googleads.properties.
my $api_client = Google::Ads::GoogleAds::Client->new();
# By default examples are set to die on any server returned fault.
$api_client->set_die_on_faults(0);
# Parameters passed on the command line will override any parameters set in code.
GetOptions("customer_id=s" => \$customer_id, "ad_group_id=i" => \$ad_group_id);
# Print the help message if the parameters are not initialized in the code nor
# in the command line.
pod2usage(2) if not check_params($customer_id, $ad_group_id);
# Call the example.
handle_rate_exceeded_error($api_client, $customer_id =~ s/-//gr, $ad_group_id);
=pod
=head1 NAME
handle_rate_exceeded_error
=head1 DESCRIPTION
Handles RateExceededError in an application. This code example runs 5 requests
sequentially, each request attempting to validate 100 keywords. While it is
unlikely that running these requests would trigger a rate exceeded error,
substantially increasing the number of requests may have that effect. Note that
this example is for illustrative purposes only, and you shouldn't intentionally
try to trigger a rate exceed error in your application.
=head1 SYNOPSIS
handle_rate_exceeded_error.pl [options]
-help Show the help message.
-customer_id The Google Ads customer ID.
-ad_group_id The ad group ID.
=cut
جز در مواردی که غیر از این ذکر شده باشد،محتوای این صفحه تحت مجوز Creative Commons Attribution 4.0 License است. نمونه کدها نیز دارای مجوز Apache 2.0 License است. برای اطلاع از جزئیات، به خطمشیهای سایت Google Developers مراجعه کنید. جاوا علامت تجاری ثبتشده Oracle و/یا شرکتهای وابسته به آن است.
تاریخ آخرین بهروزرسانی 2025-02-26 بهوقت ساعت هماهنگ جهانی.
[null,null,["تاریخ آخرین بهروزرسانی 2025-02-26 بهوقت ساعت هماهنگ جهانی."],[[["The code demonstrates how to handle `RateExceededError` in Google Ads API calls using multithreading and a retry mechanism with exponential backoff."],["It simulates keyword validation with multiple threads to illustrate error handling in a high-request scenario."],["The retry logic helps manage temporary rate limiting by pausing and retrying requests with increasing delays."],["The code uses C#, PHP, Python, and Ruby, showcasing error handling across different programming languages."],["It emphasizes the importance of respecting Google Ads API rate limits and implementing strategies to avoid disruptions in real-world applications."]]],[]]