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ılamazlığı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'leri 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 genel bir bilgi verir. 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 modeli 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.
Kısmi arıza modeliyle karşılaştırma
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 fark edebilirsiniz.
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.
validateOnly ile hızlı hata kontrolü yapma
Çoğu alma ve kaldırma isteği validateOnly alanını destekler. validateOnly değerini true olarak ayarladığınızda Data Manager API, normal bir istekte olduğu gibi aynı temel doğrulama kontrollerini çalıştırır ancak herhangi bir veriyi almaz veya kaldırmaz.
- İstek hatalıysa normal bir istekten alacağınız hata yanıtıyla başarısız olur.
- İstek doğrulamayı geçerse başarılı olur. Yanıt, normal bir istekte olduğu gibi isteğe bağlı alanlar için herhangi bir
fieldWarningsiçerir.
validateOnly ile yapabilecekleriniz:
- Canlı verilerinizi etkilemeden yeni veya güncellenmiş bir entegrasyonu test edin.
- İsteği yeniden göndermeden önce düzeltmenin hatayı çözdüğünü onaylayın.
Hataları işleme
Bir istek başarısız olduğunda şu adımları uygulayın:
Hata türünü bulmak için hata kodunu kontrol edin.
- gRPC kullanıyorsanız hata kodu,
Statusöğesinincodealanı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 koduINVALID_ARGUMENTisecom.google.api.gax.rpc.InvalidArgumentExceptionhatası verir. - REST kullanıyorsanız hata kodu
error.statuskonumundaki hata yanıtında, ilgili HTTP durumu iseerror.codekonumundadır.
- gRPC kullanıyorsanız hata kodu,
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,HelpveLocalizedMessageyüklerini kontrol etmenizi ve günlüğe kaydetmenizi öneririz.ErrorInfo, diğer yüklerde bulunmayabilecek bilgiler içerir.RequestInfo, destek ekibiyle iletişime geçmeniz gerekirse yararlı olacak istek kimliğine sahiptir.HelpveLocalizedMessage, hatayı gidermenize yardımcı olacak bağlantılar ve diğer ayrıntıları içerir.
Ayrıca,
BadRequestyükü, hangi alanların hataya neden olduğu hakkında bilgi sağladığındanINVALID_ARGUMENThataları 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), fieldWarnings 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 (
repeatedalanı) 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.descriptionBelirtilen değerin neden uyarıya yol açtığına dair açıklama.
reasonUyarı türünü tanımlayan
WarningReasonenum değeri.
FieldWarning ile örnek
Aşağıda, alışveriş sepetindeki öğelerden birinin satıcı ürün kimliği eksik olduğu için uyarı içeren başarılı bir alım isteğine ilişkin örnek yanıt verilmiştir.
{
"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
BadRequestfield_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 (
repeatedalanı) işaret ediyorsa dizini, listenin adından sonra köşeli parantez içinde ([...]) gösterilir.Örneğin,
destinations[0].operating_account.account_id,destinationslistesindeki ilk öğeninoperating_accountbölümündekiaccount_idöğesidir.descriptionDeğerin neden hataya yol açtığına dair açıklama.
reasonINVALID_HEX_ENCODINGveyaINVALID_CURRENCY_CODEgibiErrorReasonenum'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, alan ihlali olan accountId öğesinin destinations listesindeki ilk öğenin login_account içinde 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:
İlk
event, etkinliğin ikinci kullanıcı kimliğinde onaltılık kodlanmamış bir değere sahip.İkinci
event, etkinliğin üçüncü kullanıcı kimliğinde 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, Data Manager API'nin etkinleştirilmediği bir Google Cloud projesi için kimlik bilgilerinin kullanılmasından kaynaklanan PERMISSION_DENIED hatasıyla ilgili ErrorInfo'yı burada bulabilirsiniz. ErrorInfo simgesi, hatayla ilgili ek bilgiler sağlar. Örneğin:
- İstekle ilişkili proje,
metadata.consumeraltında. metadata.serviceTitlealtındaki hizmetin adı.- Hizmetin etkinleştirilebileceği URL,
metadata.activationUrlaltı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"
}
},
...
]
}
}
Kota ve sıklık sınırlaması hataları
Bir istek proje sınırını aştığında API, RESOURCE_EXHAUSTED hatası (HTTP durum kodu 429) döndürür. ErrorInfo yükü, metadata eşlemesinde hangi sınırın aşıldığıyla ilgili ayrıntılar sağlar:
consumer- İstekle ilişkili Google Cloud projesi,
şu şekilde biçimlendirilmiş:
projects/PROJECT_NUMBER. quota_limit- Aşılan kota sınırının adı (ör.
IngestionMutateRequestsPerMinutePerProjectveyaIngestionMutateRequestsPerDayPerProject). Uygulamanın dakika başına sınırı veya günlük sınırı aşıp aşmadığını belirlemek için bu değeri kullanabilirsiniz. Sınır adlarının tam listesi için Proje sınırları bölümüne bakın. quota_location- Kotanın uygulandığı konum. Data Manager API için bu değer her zaman
global'dır. quota_metric- Sınırla ilişkili metrik (ör.
datamanager.googleapis.com/ingestion_mutate_requests). service- Hizmetin adı,
datamanager.googleapis.com.
Aşağıda, bir istek, alım değişiklik istekleri için dakikadaki sınırı aştığında verilen RESOURCE_EXHAUSTED hata yanıtına dair bir örnek verilmiştir:
{
"error": {
"code": 429,
"message": "Quota exceeded for quota metric 'Ingestion mutate requests' and limit 'Ingestion mutate requests per minute' of service 'datamanager.googleapis.com' for consumer 'project_number:PROJECT_NUMBER'.",
"status": "RESOURCE_EXHAUSTED",
"details": [
{
"@type": "type.googleapis.com/google.rpc.ErrorInfo",
"reason": "RATE_LIMIT_EXCEEDED",
"domain": "googleapis.com",
"metadata": {
"consumer": "projects/PROJECT_NUMBER",
"quota_limit": "IngestionMutateRequestsPerMinutePerProject",
"quota_location": "global",
"quota_metric": "datamanager.googleapis.com/ingestion_mutate_requests",
"service": "datamanager.googleapis.com"
}
}
]
}
}
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ü, hizmetin etkinleştirilebileceği URL'yi gösterir ve LocalizedMessage, hatanın açıklamasını içerir.
{
"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...
// If handling a rate limit error, check the exceeded quota limit:
if (errorInfo.Reason == "RATE_LIMIT_EXCEEDED" &&
errorInfo.Metadata.TryGetValue("quota_limit", out string quotaLimit))
{
// Inspect quotaLimit to determine whether it is a per-minute
// or daily limit (for example,
// IngestionMutateRequestsPerMinutePerProject).
}
// 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'...
// If handling a rate limit error, check the exceeded quota limit:
if (errorInfo != null && "RATE_LIMIT_EXCEEDED".equals(errorInfo.getReason())) {
String quotaLimit = errorInfo.getMetadataMap().get("quota_limit");
// Inspect quotaLimit to determine whether it is a per-minute
// or daily limit (for example,
// IngestionMutateRequestsPerMinutePerProject).
}
// 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 = apiException.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.
- Göndermeden önce doğrulama
- Bir entegrasyon oluşturduğunuzda veya değiştirdiğinizde, verileri almadan önce hızlı hata hatalarını yakalamak için
validateOnlydeğerinitrueolarak ayarlayarak istek gönderin. - Hata ayrıntılarını inceleme
- Her zaman
BadRequestgibi 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,UNAUTHENTICATEDgibi kodlar. Bunlar, isteğin veya uygulamanızın durumu/kimlik bilgilerinde değişiklik yapılmasını gerektirir. Sorunu gidermeden isteği yeniden göndermeyin. - Sunucu hataları:
UNAVAILABLE,INTERNAL,DEADLINE_EXCEEDED,UNKNOWNgibi kodlar. Bunlar, API hizmetiyle ilgili geçici bir soruna işaret eder.
- İstemci hataları:
- Yeniden deneme stratejisi uygulama
Hatayı yeniden denemenin mümkün olup olmadığını belirleyin ve yeniden deneme stratejisi kullanın.
Yalnızca geçici sunucu hataları (ör.
UNAVAILABLE,DEADLINE_EXCEEDED,INTERNAL,UNKNOWNveABORTED) ve dakikadaki sıklık sınırları (RESOURCE_EXHAUSTEDileRATE_LIMIT_EXCEEDED) için yeniden deneme yapın.Hız sınırları için
quota_limitinErrorInfo:Sınır dakika başına ise (ör.
IngestionMutateRequestsPerMinutePerProject), istekleri duraklatın ve jitter ile eksponansiyel geri yükleme kullanarak yeniden deneyin.Sınır günlükse (ör.
IngestionMutateRequestsPerDayPerProject) hemen yeniden denemeyin. Günlük kota Pasifik Saati'ne göre gece yarısında sıfırlanana kadar işlemeyi duraklatın.
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 ve maksimum yeniden deneme sayısı 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.