API hatalarını anlama

Bu kılavuzda, Data Manager API'sinin hataları nasıl işlediği ve ilettiği açıklanmaktadır. API hatalarının yapısını ve anlamını anlamak, geçersiz girişten geçici hizmet kullanılamamasına kadar sorunları düzgün bir şekilde ele alabilen sağlam uygulamalar oluşturmak için çok önemlidir.

Data Manager API, gRPC durum kodlarına dayalı olan standart Google API hata modelini kullanır. Hataya neden olan her API yanıtı, aşağıdakileri içeren bir Status nesnesi içerir:

  • Sayısal bir hata kodu.
  • Hata mesajı
  • İsteğe bağlı, ek hata ayrıntıları.

Standart hata kodları

Data Manager API, gRPC ve HTTP tarafından tanımlanan bir dizi standart hata kodu kullanır. Bu kodlar, hata türü hakkında üst düzey bir gösterge sağlar. Sorunun temel niteliğini anlamak için her zaman önce bu kodu kontrol etmelisiniz.

Bu kodlar hakkında daha fazla bilgi için API Tasarım Kılavuzu - Hata kodları başlıklı makaleyi inceleyin.

Hızlı hata tespiti modeli

Data Manager API, hızlı hata modelini kullanır. Bir istek yapısal hatalar içeriyorsa veya herhangi bir kayıt gerekli bir alan için doğrulanamıyorsa isteğin tamamı başarısız olur ve API, bu istekteki verilerin hiçbirini işlemez.

Hızlı hata modeli, Google Ads API ve Campaign Manager 360 API gibi diğer bazı Google API'lerindeki kısmi hata modelinden farklıdır. Kısmi hata modelinde, bazı kayıtlarda hata olsa bile istek başarılı olur ve yanıtta başarısız olan kayıtlarla ilgili hata ayrıntıları yer alır.

Kısmi hata kullanışlı olsa da kısmi hata modeli sizi hatalar konusunda proaktif olarak uyarmadığından önemli riskler taşır. Her yanıttaki hataları açıkça kontrol etmeniz gerekir. Bu durum, istekteki kayıtların çoğu veya tamamı API tarafından reddedilse bile istek başarılı olduğundan önemli sorunları gizleyebilir. Bir istekteki kayıtların önemli bir bölümünde hata varsa ancak yanıtı incelemezseniz verilerinizdeki yaygın sorunlardan tamamen habersiz olabilirsiniz. Bu sorunları ancak günler veya haftalar sonra, kümülatif sonuçlar beklentilerinizle uyuşmadığında keşfedebilirsiniz.

Hızlı hata modeli, verileriniz veya entegrasyonunuzla ilgili sorunlar konusunda sizi anında uyararak bu tuzaklardan kaçınmanızı sağlar. Böylece uygun önlemleri alabilirsiniz.

Hataları işleme

Bir istek başarısız olduğunda şu adımları uygulayın:

  1. Hata türünü bulmak için hata kodunu kontrol edin.

    • gRPC kullanıyorsanız hata kodu, Status öğesinin code alanında yer alır. İstemci kitaplığı kullanıyorsanız hata koduna karşılık gelen belirli bir istisna türü oluşturabilir. Örneğin, Java için istemci kitaplığı, hata kodu INVALID_ARGUMENT ise com.google.api.gax.rpc.InvalidArgumentException hatası verir.
    • REST kullanıyorsanız hata kodu error.status konumundaki hata yanıtında, ilgili HTTP durumu ise error.code konumundadır.
  2. Hata kodu için standart ayrıntı yükünü kontrol edin. Standart ayrıntı yükleri, Google API'lerinden gelen hatalarla ilgili bir mesaj kümesidir. Hata ayrıntılarını yapılandırılmış ve tutarlı bir şekilde gösterir. Data Manager API'deki her hata birden fazla standart ayrıntı yükü mesajı içerebilir. Data Manager API istemci kitaplıklarında, bir hatadan standart ayrıntı yüklerini almak için yardımcı yöntemler bulunur.

    Hata kodu ne olursa olsun ErrorInfo, RequestInfo, Help ve LocalizedMessage yüklerini kontrol edip günlüğe kaydetmenizi öneririz.

    • ErrorInfo, diğer yüklerde bulunmayabilecek bilgiler içerir.
    • RequestInfo, destek ekibiyle iletişime geçmeniz gerektiğinde yararlı olan istek kimliğine sahiptir.
    • Help ve LocalizedMessage, hatayı gidermenize yardımcı olacak bağlantılar ve diğer ayrıntıları içerir.

    Ayrıca, BadRequest yükü, hangi alanların hataya neden olduğu hakkında bilgi sağladığından INVALID_ARGUMENT hataları için de yararlıdır.

Aktarım uyarıları

Data Manager API, mümkün olduğunca çok sayıda alım isteğini kabul eder. Gerekli olmayan veriler eklerseniz bu alanlarla ilgili doğrulama hataları isteğin başarısız olmasına neden olmaz. Örneğin, bir alışveriş sepeti öğesinde satıcı ürün kimliği eksikse API, isteğin geri kalanını işler ve uyarı döndürür.

Başarılı bir alım yanıtı (HTTP durum kodu 200), field_warnings listesinde şu uyarıları içerir. Her giriş, aşağıdaki alanları içeren bir FieldWarning nesnesidir:

field

İstekteki alanın konumu, snake case yol söz diziminde.

Bir yol, listedeki bir öğeyi (repeated alanı) işaret ediyorsa dizini, listenin adından sonra köşeli parantez içinde ([...]) gösterilir.

Örneğin, events.events[0].cart_data.items[0].merchant_product_id, istekteki ilk etkinliğin alışveriş sepeti verilerindeki ilk öğeyle ilgili bir uyarıyı tanımlar.

description

Belirtilen değerin neden uyarıya yol açtığına dair açıklama.

reason

Uyarı türünü tanımlayan WarningReason enum değeri.

FieldWarning ile örnek

Bir alışveriş sepeti öğesinde satıcı ürün kimliği eksik olduğundan uyarı içeren başarılı bir alım isteğine ilişkin örnek yanıtı aşağıda bulabilirsiniz.

{
  "requestId": "126365e1-16d0-4c81-9de9-f362711e250a",
  "fieldWarnings": [
    {
      "field": "events.events[0].cart_data.items[0].merchant_product_id",
      "description": "The merchant product ID is missing in the cart item.",
      "reason": "WARNING_REASON_CART_DATA_ITEM_MERCHANT_PRODUCT_ID_MISSING"
    }
  ]
}

Standart ayrıntı yükleri

Data Manager API için en yaygın standart ayrıntı yükleri şunlardır:

BadRequest

Bir istek INVALID_ARGUMENT (HTTP durum kodu 400) ile başarısız olduğunda BadRequest yükünü kontrol edin.

BadRequest mesajı, isteğin kötü değerlere sahip alanlar içerdiğini veya zorunlu bir alan için değerin eksik olduğunu gösterir. Hangi alanlarda hata olduğunu bulmak için BadRequest field_violations listesini kontrol edin. Her field_violations girişinde, hatayı düzeltmenize yardımcı olacak bilgiler bulunur:

field

İstekteki alanın konumu, snake case yol söz diziminde.

Bir yol, listedeki bir öğeyi (repeated alanı) işaret ediyorsa dizini, listenin adından sonra köşeli parantez içinde ([...]) gösterilir.

Örneğin, destinations[0].operating_account.account_id, destinations listesindeki ilk öğenin operating_account bölümündeki account_id öğesidir.

description

Değerin neden hataya yol açtığına dair açıklama.

reason

INVALID_HEX_ENCODING veya INVALID_CURRENCY_CODE gibi ErrorReason enum'u.

BadRequest örnekleri

BadRequest mesajı içeren bir INVALID_ARGUMENT hatasıyla ilgili örnek yanıtı aşağıda bulabilirsiniz. field_violations, hatanın accountId olmayan bir sayı olduğunu gösterir. field değeri destinations[0].login_account.account_id, accountId alan ihlali olan login_account öğesinin destinations listesindeki ilk öğe olduğunu gösterir.

{
  "error": {
    "code": 400,
    "message": "There was a problem with the request.",
    "status": "INVALID_ARGUMENT",
    "details": [
      {
        "@type": "type.googleapis.com/google.rpc.ErrorInfo",
        "reason": "INVALID_ARGUMENT",
        "domain": "datamanager.googleapis.com",
        "metadata": {
          "requestId": "t-a8896317-069f-4198-afed-182a3872a660"
        }
      },
      {
        "@type": "type.googleapis.com/google.rpc.RequestInfo",
        "requestId": "t-a8896317-069f-4198-afed-182a3872a660"
      },
      {
        "@type": "type.googleapis.com/google.rpc.BadRequest",
        "fieldViolations": [
          {
            "field": "destinations[0].login_account.account_id",
            "description": "String is not a valid number.",
            "reason": "INVALID_NUMBER_FORMAT"
          }
        ]
      }
    ]
  }
}

BadRequest mesajı içeren bir INVALID_ARGUMENT hatasından alınan başka bir örnek yanıtı aşağıda bulabilirsiniz. Bu durumda, field_violations listesinde iki hata gösterilir:

  1. İlk event, etkinliğin ikinci kullanıcı tanımlayıcısında onaltılık kodlanmamış bir değere sahip.

  2. İkinci event, etkinliğin üçüncü kullanıcı tanımlayıcısında onaltılık olarak kodlanmamış bir değere sahip.

{
  "error": {
    "code": 400,
    "message": "There was a problem with the request.",
    "status": "INVALID_ARGUMENT",
    "details": [
      {
        "@type": "type.googleapis.com/google.rpc.ErrorInfo",
        "reason": "INVALID_ARGUMENT",
        "domain": "datamanager.googleapis.com",
        "metadata": {
          "requestId": "t-6bc8fb83-d648-4942-9c49-2604276638d8"
        }
      },
      {
        "@type": "type.googleapis.com/google.rpc.RequestInfo",
        "requestId": "t-6bc8fb83-d648-4942-9c49-2604276638d8"
      },
      {
        "@type": "type.googleapis.com/google.rpc.BadRequest",
        "fieldViolations": [
          {
            "field": "events.events[0].user_data.user_identifiers[1]",
            "description": "The HEX encoded value is malformed.",
            "reason": "INVALID_HEX_ENCODING"
          },
          {
            "field": "events.events[1].user_data.user_identifiers[2]",
            "description": "The HEX encoded value is malformed.",
            "reason": "INVALID_HEX_ENCODING"
          }
        ]
      }
    ]
  }
}

RequestInfo

Bir istek başarısız olduğunda RequestInfo yükünü kontrol edin. RequestInfo, API isteğinizi benzersiz şekilde tanımlayan request_id içerir.

{
  "@type": "type.googleapis.com/google.rpc.RequestInfo",
  "requestId": "t-4490c640-dc5d-4c28-91c1-04a1cae0f49f"
}

Hataları günlüğe kaydederken veya destek ekibiyle iletişime geçerken sorunların teşhis edilmesine yardımcı olmak için istek kimliğini eklediğinizden emin olun.

ErrorInfo

Diğer standart ayrıntı yüklerinde yakalanmamış olabilecek ek bilgileri almak için ErrorInfo mesajını kontrol edin. ErrorInfo yükü, hatayla ilgili bilgileri içeren bir metadata haritası içerir.

Örneğin, Veri Yöneticisi API'sinin etkinleştirilmediği bir Google Cloud projesinin kimlik bilgilerinin kullanılması nedeniyle oluşan PERMISSION_DENIED hatasıyla ilgili ErrorInfo kodunu burada bulabilirsiniz. ErrorInfo, hata hakkında aşağıdaki gibi ek bilgiler sağlar:

  • İstekle ilişkili proje, metadata.consumer altında.
  • metadata.serviceTitle altındaki hizmetin adı.
  • Hizmetin etkinleştirilebileceği URL, metadata.activationUrl altında yer alır.
{
  "error": {
    "code": 403,
    "message": "Data Manager API has not been used in project PROJECT_NUMBER before or it is disabled. Enable it by visiting https://console.cloud.google.com/apis/api/datamanager.googleapis.com/overview?project=PROJECT_NUMBER then retry. If you enabled this API recently, wait a few minutes for the action to propagate to our systems and retry.",
    "status": "PERMISSION_DENIED",
    "details": [
      {
        "@type": "type.googleapis.com/google.rpc.ErrorInfo",
        "reason": "SERVICE_DISABLED",
        "domain": "googleapis.com",
        "metadata": {
          "consumer": "projects/PROJECT_NUMBER",
          "service": "datamanager.googleapis.com",
          "containerInfo": "PROJECT_NUMBER",
          "serviceTitle": "Data Manager API",
          "activationUrl": "https://console.cloud.google.com/apis/api/datamanager.googleapis.com/overview?project=PROJECT_NUMBER"
        }
      },
      ...
    ]
  }
}

Help ve LocalizedMessage

Hatayı anlamanıza ve düzeltmenize yardımcı olacak doküman bağlantılarını ve yerelleştirilmiş hata mesajlarını almak için Help ve LocalizedMessage yüklerini kontrol edin.

Örneğin, Data Manager API'nin etkin olmadığı bir Google Cloud projesinin kimlik bilgilerinin kullanılması nedeniyle oluşan PERMISSION_DENIED hatası için Help ve LocalizedMessage aşağıda verilmiştir. Help yükünde, hizmetin etkinleştirilebileceği URL gösterilir ve LocalizedMessage içinde hatanın açıklaması yer alır.

{
  "error": {
    "code": 403,
    "message": "Data Manager API has not been used in project PROJECT_NUMBER before or it is disabled. Enable it by visiting https://console.cloud.google.com/apis/api/datamanager.googleapis.com/overview?project=PROJECT_NUMBER then retry. If you enabled this API recently, wait a few minutes for the action to propagate to our systems and retry.",
    "status": "PERMISSION_DENIED",
    "details": [
      {
        "@type": "type.googleapis.com/google.rpc.LocalizedMessage",
        "locale": "en-US",
        "message": "Data Manager API has not been used in project PROJECT_NUMBER before or it is disabled. Enable it by visiting https://console.cloud.google.com/apis/api/datamanager.googleapis.com/overview?project=PROJECT_NUMBER then retry. If you enabled this API recently, wait a few minutes for the action to propagate to our systems and retry."
      },
      {
        "@type": "type.googleapis.com/google.rpc.Help",
        "links": [
          {
            "description": "Google API Console API activation",
            "url": "https://console.cloud.google.com/apis/api/datamanager.googleapis.com/overview?project=PROJECT_NUMBER"
          }
        ]
      },
      ...
    ]
  }
}

Hata ayrıntılarına erişme

İstemci kitaplıklarından birini kullanıyorsanız standart ayrıntı yüklerini almak için yardımcı yöntemleri kullanın.

.NET

try {
    // Send API request
}
catch (Grpc.Core.RpcException rpcException)
{
    Console.WriteLine($"Exception encountered: {rpcException.Message}");
    var statusDetails =
        Google.Api.Gax.Grpc.RpcExceptionExtensions.GetAllStatusDetails(
            rpcException
        );
    foreach (var detail in statusDetails)
    {
        if (detail is Google.Rpc.BadRequest)
        {
            Google.Rpc.BadRequest badRequest = (Google.Rpc.BadRequest)detail;
            foreach (
                BadRequest.Types.FieldViolation? fieldViolation in badRequest.FieldViolations
            )
            {
                // Access attributes such as fieldViolation!.Reason and fieldViolation!.Field
            }
        }
        else if (detail is Google.Rpc.RequestInfo)
        {
            Google.Rpc.RequestInfo requestInfo = (Google.Rpc.RequestInfo)detail;
            string requestId = requestInfo.RequestId;
            // Log the requestId...
        }
        else if (detail is Google.Rpc.ErrorInfo)
        {
            Google.Rpc.ErrorInfo errorInfo = (Google.Rpc.ErrorInfo)detail;
            // Log the errorInfo.Reason and errorInfo.Metadata...

            // Log the details in the 'Metadata' map...
            foreach (
                KeyValuePair<String, String> metadataEntry in errorInfo.Metadata
            )
            {
                // Log the metadataEntry.Key and metadataEntry.Value...
            }
        }
        else
        {
            // ...
        }
    }
}

Java

try {
  // Send API request
} catch (com.google.api.gax.rpc.InvalidArgumentException invalidArgumentException) {
  // Gets the standard BadRequest payload from the exception.
  BadRequest badRequest = invalidArgumentException.getErrorDetails().getBadRequest();
  for (int i = 0; i < badRequest.getFieldViolationsCount(); i++) {
    FieldViolation fieldViolation = badRequest.getFieldViolations(i);
    // Access attributes such as fieldViolation.getField() and fieldViolation.getReason()
  }

  // Gets the standard RequestInfo payload from the exception.
  RequestInfo requestInfo = invalidArgumentException.getErrorDetails().getRequestInfo();
  if (requestInfo != null) {
    String requestId = requestInfo.getRequestId();
    // Log the requestId...
  }
} catch (com.google.api.gax.rpc.ApiException apiException) {
  // Fallback exception handler for other types of ApiException.

  // Gets the standard ErrorInfo payload from the exception.
  ErrorInfo errorInfo = apiException.getErrorDetails().getErrorInfo();
  // Log the 'reason' and 'domain'...

  // Log the details in the 'metadata' map...
  for (Entry<String, String> metadataEntry : errorInfo.getMetadataMap().entrySet()) {
    // Log the metadataEntry key and value...
  }

  // Gets the standard RequestInfo payload from the exception.
  RequestInfo requestInfo = invalidArgumentException.getErrorDetails().getRequestInfo();
  if (requestInfo != null) {
    String requestId = requestInfo.getRequestId();
    // Log the requestId...
  }
  ...
}

Hata işleme ile ilgili en iyi uygulamalar

Esnek uygulamalar oluşturmak için aşağıdaki en iyi uygulamaları uygulayın.

Hata ayrıntılarını inceleme
Her zaman BadRequest gibi standart ayrıntı yüklerinden birini arayın. Her standart ayrıntı yükü, hatanın nedenini anlamanıza yardımcı olacak bilgiler içerir.
İstemci ve sunucu hatalarını ayırt etme

Hataya, uygulamanızla (istemci) ilgili bir sorunun mu yoksa API ile (sunucu) ilgili bir sorunun mu neden olduğunu belirleyin.

  • İstemci hataları: INVALID_ARGUMENT, NOT_FOUND, PERMISSION_DENIED, FAILED_PRECONDITION, UNAUTHENTICATED gibi kodlar. Bu durumda, istekte veya uygulamanızın durumunda/kimlik bilgilerinde değişiklik yapmanız gerekir. Sorunu çözmeden isteği yeniden göndermeyin.
  • Sunucu hataları: UNAVAILABLE, INTERNAL, DEADLINE_EXCEEDED, UNKNOWN gibi kodlar. Bunlar, API hizmetiyle ilgili geçici bir soruna işaret eder.
Yeniden deneme stratejisi uygulama

Hatayı yeniden denemenin mümkün olup olmadığını belirleyin ve yeniden deneme stratejisi kullanın.

  • Yalnızca UNAVAILABLE, DEADLINE_EXCEEDED, INTERNAL, UNKNOWN ve ABORTED gibi geçici sunucu hataları için yeniden deneyin.
  • Yeniden denemeler arasında artan sürelerle beklemek için eksponansiyel geri yükleme algoritması kullanın. Bu, zaten stresli olan bir hizmetin aşırı yüklenmesini önlemeye yardımcı olur. Örneğin, önce 1 saniye, sonra 2 saniye, sonra 4 saniye bekleyin. Maksimum yeniden deneme sayısına veya toplam bekleme süresine ulaşana kadar bu şekilde devam edin.
  • Birçok istemcinin aynı anda yeniden denediği "gürleyen sürü" sorununu önlemek için geri çekilme gecikmelerine küçük bir rastgele "titreme" miktarı ekleyin.
Kapsamlı günlük kaydı

Tüm standart ayrıntı yükleri dahil olmak üzere hata yanıtının tamamını, özellikle de istek kimliğini kaydedin. Bu bilgiler, hata ayıklama ve gerektiğinde sorunları Google Destek Ekibi'ne bildirme açısından önemlidir.

Kullanıcı geri bildirimi sağlama

Standart ayrıntı yüklerindeki kodlara ve mesajlara göre uygulamanızın kullanıcılarına net ve faydalı geri bildirimler sağlayın. Örneğin, yalnızca "Bir hata oluştu" demek yerine "İşlem kimliği eksikti" veya "Hedefin hesap kimliği bulunamadı" diyebilirsiniz.

Bu yönergeleri uygulayarak Data Manager API'sinin döndürdüğü hataları etkili bir şekilde teşhis edip işleyebilir, böylece daha kararlı ve kullanıcı dostu uygulamalar oluşturabilirsiniz.