googleads / google-ads-php

Google Ads API Client Library for PHP
https://developers.google.com/google-ads/api/docs/client-libs/php
Apache License 2.0
295 stars 262 forks source link

Failed to parse binary descriptor #640

Closed rpmgr closed 3 years ago

rpmgr commented 3 years ago

Hi,

My code is working fine on Dev server but throws Error on Production server, am I missing anything on Production?

Error: Fatal Error (1): Failed to parse binary descriptor in [../app/Vendor/googleads/google-ads-php/metadata/Google/Ads/GoogleAds/V8/Services/ConversionUploadService.php, line 124]

Thanks in advance.

PierrickVoulet commented 3 years ago

Hi @rpmgr,

I tried to reproduce this issue without success so far. Could you provide the following information?

Your environment:

_You can paste the output generated by our complementary script: https://github.com/googleads/google-ads-php/blob/master/scripts/print_php_information.php._

Alternatively, please provide with the following pieces of information:

Steps to reproduce:

You can paste the piece of code that fails here.

rpmgr commented 3 years ago

Environment:

================= PHP GENERAL INFORMATION
PHP Version 7.4.22 --
================= PHP EXTENSION INFORMATION
The PHP Extension grpc is installed: 1.39.0.
The PHP Extension protobuf is installed: 3.17.3.
Since, I've installed the gRPC PHP extension, I think the client library is using `grpc` as a transport.

Additional information:

FYI: PHP Version and gRPC version in my dev is 7.4.21 and 1.38.0 respectively. OS in dev is Ubuntu 18.04.3 LTS and Debian 4.19.194-3 in production.

================================= Steps to reproduce: While trying to upload conversion I get the error.

Piece of code that fails:

namespace GPBMetadata\Google\Ads\GoogleAds\V8\Services;

class ConversionUploadService { public static $is_initialized = false;

public static function initOnce() {
    $pool = \Google\Protobuf\Internal\DescriptorPool::getGeneratedPool();
    if (static::$is_initialized == true) {
      return;
    }
    \GPBMetadata\Google\Api\Http::initOnce();
    \GPBMetadata\Google\Api\Annotations::initOnce();
    \GPBMetadata\Google\Api\FieldBehavior::initOnce();
    \GPBMetadata\Google\Api\Resource::initOnce();
    \GPBMetadata\Google\Api\Client::initOnce();
    \GPBMetadata\Google\Protobuf\Any::initOnce();
    \GPBMetadata\Google\Rpc\Status::initOnce();
    $pool->internalAddGeneratedFile(
        '

� @google/ads/googleads/v8/services/conversion_upload_service.proto google.ads.googleads.v8.servicesgoogle/api/client.protogoogle/api/field_behavior.protogoogle/api/resource.protogoogle/rpc/status.proto"� UploadClickConversionsRequest customer_id ( B�AK conversions ( 21.google.ads.googleads.v8.services.ClickConversionB�A partial_failure (B�A

validate_only ("� UploadClickConversionsResponse1 partial_failure_error ( 2.google.rpc.StatusH results ( 27.google.ads.googleads.v8.services.ClickConversionResult"� UploadCallConversionsRequest customer_id ( B�AJ conversions ( 20.google.ads.googleads.v8.services.CallConversionB�A partial_failure (B�A

validate_only ("� UploadCallConversionsResponse1 partial_failure_error ( 2.google.rpc.StatusG results ( 26.google.ads.googleads.v8.services.CallConversionResult"� ClickConversion gclid ( H � conversion_action ( H�! conversion_date_time ( H� conversion_value (H�

currency_code ( H� order_id ( H�\\ external_attribution_data ( 29.google.ads.googleads.v8.services.ExternalAttributionDataJ custom_variables ( 20.google.ads.googleads.v8.services.CustomVariable= cart_data ( 2*.google.ads.googleads.v8.services.CartDataB _gclidB _conversion_actionB _conversion_date_timeB _conversion_valueB _currency_codeB _order_id"� CallConversion caller_id ( H �! call_start_date_time ( H� conversion_action ( H�! conversion_date_time ( H� conversion_value (H�

currency_code ( H�J custom_variables ( 20.google.ads.googleads.v8.services.CustomVariableB

_caller_idB _call_start_date_timeB _conversion_actionB _conversion_date_timeB _conversion_valueB _currency_code"� ExternalAttributionData( external_attribution_credit (H �\' external_attribution_model ( H�B _external_attribution_creditB _external_attribution_model"� ClickConversionResult gclid ( H � conversion_action ( H�! conversion_date_time ( H�B _gclidB _conversion_actionB _conversion_date_time"� CallConversionResult caller_id ( H �! call_start_date_time ( H� conversion_action ( H�! conversion_date_time ( H�B

_caller_idB _call_start_date_timeB _conversion_actionB _conversion_date_time"{ CustomVariableZ conversion_custom_variable ( B6�A3 1googleads.googleapis.com/ConversionCustomVariable value ( "� CartData merchant_id (  feed_country_code (  feed_language_code (  local_transaction_cost (> items ( 2/.google.ads.googleads.v8.services.CartData.Item@ Item

product_id (  quantity (

unit_price (2� ConversionUploadService� UploadClickConversions?.google.ads.googleads.v8.services.UploadClickConversionsRequest@.google.ads.googleads.v8.services.UploadClickConversionsResponse"i���9"4/v8/customers/{customer_id=*}:uploadClickConversions:*�A\'customer_id,conversions,partial_failure� UploadCallConversions>.google.ads.googleads.v8.services.UploadCallConversionsRequest?.google.ads.googleads.v8.services.UploadCallConversionsResponse"h���8"3/v8/customers/{customer_id=*}:uploadCallConversions:*�A\'customer_id,conversions,partial_failureE�Agoogleads.googleapis.com�A\'https://www.googleapis.com/auth/adwordsB� $com.google.ads.googleads.v8.servicesBConversionUploadServiceProtoPZHgoogle.golang.org/genproto/googleapis/ads/googleads/v8/services;services�GAA� Google.Ads.GoogleAds.V8.Services� Google\\Ads\\GoogleAds\\V8\\Services�$Google::Ads::GoogleAds::V8::Servicesbproto3' , true); static::$is_initialized = true; }

rpmgr commented 3 years ago

Hi @PierrickVoulet,

Some background: I've installed C implementation of grpc and protobuf using PECL. I've installed the client library using composer install and I think, it might have installed the PHP version of grpc and protobuf as well to use with rest?

To reproduce the error:

  1. Enable C implementation of grpc in php.ini file.
  2. When I specify the transport as rest in the code using following line: ->withTransport('rest')

I get the following error: #0 /home/vagrant/google-oct/app/Vendor/google/gax/src/Transport/RestTransport.php(125): Google\Protobuf\Internal\Message->mergeFromJsonString() #1 /home/vagrant/google-oct/app/Vendor/guzzlehttp/promises/src/Promise.php(204): Google\ApiCore\Transport\RestTransport->Google\ApiCore\Transport\{closure}() #2 /home/vagrant/google-oct/app/Vendor/guzzlehttp/promises/src/Promise.php(153): GuzzleHttp\Promise\Promise::callHandler() #3 /home/vagrant/google-oct/app/Vendor/guzzlehttp/promises/src/TaskQueue.php(48): GuzzleHttp\Promise\Promise::GuzzleHttp\Promise\{closure}() #4 /home/vagrant/google-oct/app/Vendor/guzzlehttp/guzzle/src/Handler/CurlMultiHandler.php(118): GuzzleHttp\Promise\TaskQueue->run() #5 /home/vagrant/google-oct/app/Vendor/guzzlehttp/guzzle/src/Handler/CurlMultiHandler.php(145): GuzzleHttp\Handler\CurlMultiHandler->tick() #6 /home/vagrant/google-oct/app/Vendor/guzzlehttp/promises/src/Promise.php(248): GuzzleHttp\Handler\CurlMultiHandler->execute() #7 /home/vagrant/google-oct/app/Vendor/guzzlehttp/promises/src/Promise.php(224): GuzzleHttp\Promise\Promise->invokeWaitFn() #8 /home/vagrant/google-oct/app/Vendor/guzzlehttp/promises/src/Promise.php(269): GuzzleHttp\Promise\Promise->waitIfPending() #9 /home/vagrant/google-oct/app/Vendor/guzzlehttp/promises/src/Promise.php(226): GuzzleHttp\Promise\Promise->invokeWaitList() #10 /home/vagrant/google-oct/app/Vendor/guzzlehttp/promises/src/Promise.php(62): GuzzleHttp\Promise\Promise->waitIfPending() #11 /home/vagrant/google-oct/app/Vendor/googleads/google-ads-php/src/Google/Ads/GoogleAds/V8/Services/Gapic/ConversionUploadServiceGapicClient.php(302): GuzzleHttp\Promise\Promise->wait() #12 /home/vagrant/google-oct/app/Controller/Component/GoogleAdsApiComponent.php(383): Google\Ads\GoogleAds\V8\Services\Gapic\ConversionUploadServiceGapicClient->uploadClickConversions() #13 /home/vagrant/google-oct/app/Controller/Component/GoogleAdsApiComponent.php(129): GoogleAdsApiComponent->uploadOfflineConversion() #14 /home/vagrant/google-oct/app/Controller/ServicesController.php(8544): GoogleAdsApiComponent->handleOfflineConversion() #15 [internal function]: ServicesController->testGoogleAdsLib() #16 /home/vagrant/google-oct/lib/Cake/Controller/Controller.php(499): ReflectionMethod->invokeArgs() #17 /home/vagrant/google-oct/lib/Cake/Routing/Dispatcher.php(193): Controller->invokeAction() #18 /home/vagrant/google-oct/lib/Cake/Routing/Dispatcher.php(167): Dispatcher->_invoke() #19 /home/vagrant/google-oct/app/webroot/index.php(110): Dispatcher->dispatch() #20 {main}

Error: Error occurred during parsing: Error parsing JSON @7:87: Type was not found

Also, could it be that my git command line is changing LF to CRLF while pushing the file to repo. I get following warning while pushing all the libs files: The file will have its original line endings in your working directory warning: LF will be replaced by CRLF in ...

Thanks,

PierrickVoulet commented 3 years ago

@rpmgr Thank you for the additional information, this is helpful!

If you have installed the C implementation of grpc and protobuf using PECL then you can use the grpc transport, no need to set it up to rest.

Could you provide us with the actual code that you execute and that fails, and the error logs when it fails using grpc as a transport? I tried to change the end of line to CRLF on my side but, as far as I can tell, it does not make it fail on my end.

rpmgr commented 3 years ago

Hi @PierrickVoulet, thank you for your quick response.

The codes are separated into different class files as a method. I'll paste the methods involved below: public function testGoogleAdsLib() { echo 'Test Upload Conversion'; $this->getComponent('GoogleAdsApi'); $data = [ 'id' => 1, 'related_id' => 18948, 'related_table' => 'policies', 'product_type' => 'warranty', 'gclid' => 'test1', 'conversion_action_id' => 758401197, 'created' => '2021-08-26 18:50:21', ]; try { $response = $this->GoogleAdsApi->handleOfflineConversion($data); echo 'Response status: ' . $response; } catch (Exception $e) { echo '<pre>'; print_r($e->getTraceAsString()); echo '</pre>'; echo 'Error: ' . $e->getMessage(); }

    if ($this->GoogleAdsApi->hasError()) {
        echo '<pre>';
        print_r($this->GoogleAdsApi->getErrors());
        echo '</pre>';
    }

    exit();
}

/*================================================================================*/

public function handleOfflineConversion(array $data = []): bool
{
    if(empty($data)) {
        return false;
    }

    $this->resetError();
    $errors = [];

    try {
        $this->uploadOfflineConversion(
            $this->googleAdsClient,
            $this->getCustomerId($data['product_type']),
            $data['conversion_action_id'],
            $data['gclid'],
            $this->getConversionDateTime($data['created'])
        );
    } catch (GoogleAdsException $googleAdsException) {
        $errors[] = sprintf(
            "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 */
            $errors[] = sprintf(
                "\t%s: %s%s",
                $error->getErrorCode()->getErrorCode(),
                $error->getMessage(),
                PHP_EOL
            );
        }

        $this->addErrors($errors);
    } catch (ApiException $apiException) {
        $errors[] = sprintf(
            "ApiException was thrown with message '%s'.%s",
            $apiException->getMessage(),
            PHP_EOL
        );

        $this->addErrors($errors);
    }

    if ($this->hasError()) {
        $this->addLog(
            [
                'action' => 'upload',
                'data' => $data,
            ],
            $data['related_table'],
            $data['related_id']
        );

        return false;
    }

    return true;
}

/*================================================================================*/

private function uploadOfflineConversion(
    GoogleAdsClient $googleAdsClient,
    int $customerId,
    int $conversionActionId,
    string $gclid,
    string $conversionDateTime,
    string $conversionCustomVariableId = null,
    string $conversionCustomVariableValue = null
): void {
    // Creates a click conversion by specifying currency as GBP.
    $clickConversion = new ClickConversion([
        'conversion_action' => ResourceNames::forConversionAction($customerId, $conversionActionId),
        'gclid' => $gclid,
        'conversion_value' => self::CONVERSION_VALUE,
        'conversion_date_time' => $conversionDateTime,
        'currency_code' => self::CURRENCY_CODE
    ]);

    if (!is_null($conversionCustomVariableId) && !is_null($conversionCustomVariableValue)) {
        $clickConversion->setCustomVariables([
            new CustomVariable([
                'conversion_custom_variable' => ResourceNames::forConversionCustomVariable(
                    $customerId,
                    $conversionCustomVariableId
                ),
                'value' => $conversionCustomVariableValue
            ])
        ]);
    }

    // Issues a request to upload the click conversion.
    $conversionUploadServiceClient = $googleAdsClient->getConversionUploadServiceClient();
    $response = $conversionUploadServiceClient->uploadClickConversions(
        $customerId,
        [$clickConversion],
        true
    );

    if (!is_null($response->getPartialFailureError())) {
        $this->addError(
            sprintf(
                "Partial failures occurred: '%s'.%s",
                $response->getPartialFailureError()->getMessage(),
                PHP_EOL
            )
        );
    }
}`

I don't have the server access so, I would have to print the grpc error log when I run the test through browser. Is there any information as how I can do that or you could point me to right direction?

Thanks,

rpmgr commented 3 years ago

Thank you @PierrickVoulet for taking time to look into this.

I've fixed this now and this issue can be closed. It seems to be the problem with the repo, during deployment it somehow might have corrupted binary files.

However, when C implementation of grpc is enabled in php.ini and rest transport is enabled from code ->withTransport('rest') it still gives the above error.

I'm not sure if that's the intended behaviour.

Thanks,

PierrickVoulet commented 3 years ago

I am glad you found the issue and thank you for sharing the resolution.

I was able to reproduce the issue related to REST on my end as well, I created a new issue for it https://github.com/googleads/google-ads-php/issues/641.