بمجرد تحديد أو إنشاء تقرير يلبي احتياجاتك، يحين وقت لإنشاء ناتج. يتم تخزين مخرجات التقرير في ملفات التقارير التي يمكن استردادها ومعالجتها آليًا. يتم إنشاء ملف التقرير نتيجة تشغيل التقرير.
يوضح هذا الدليل بالتفصيل كيفية إنشاء ملفات التقارير آليًا عبر خدمة التقارير.
العثور على تقرير
لتنفيذ تقرير، عليك معرفة رقم تعريفه. إذا كنت قد أنشأت تقريرًا أو حدّثته للتو، يمكن العثور على هذه القيمة في الحقل id
من مورد التقرير الذي تم إرجاعه. وننصح المستخدمين بتخزين أرقام التعريف هذه التي تم عرضها للبحث لاحقًا.
إذا لم تكن تعرف رقم تعريف التقرير الذي تريد تشغيله، يمكنك استعراض قائمة جميع التقارير المتاحة للعثور على التقرير المطلوب. يوضّح المثال التالي كيفية البحث عن تقرير وفقًا لبعض المعايير المحدّدة من قِبل المستخدم:
#C
Report target = null;
ReportList reports;
String nextPageToken = null;
do {
// Create and execute the reports list request.
ReportsResource.ListRequest request = service.Reports.List(profileId);
request.PageToken = nextPageToken;
reports = request.Execute();
foreach (Report report in reports.Items) {
if (IsTargetReport(report)) {
target = report;
break;
}
}
// Update the next page token.
nextPageToken = reports.NextPageToken;
} while (target == null
&& reports.Items.Any()
&& !String.IsNullOrEmpty(nextPageToken));
Java
Report target = null;
ReportList reports;
String nextPageToken = null;
do {
// Create and execute the reports list request.
reports = reporting.reports().list(profileId).setPageToken(nextPageToken).execute();
for (Report report : reports.getItems()) {
if (isTargetReport(report)) {
target = report;
break;
}
}
// Update the next page token.
nextPageToken = reports.getNextPageToken();
} while (target == null
&& !reports.getItems().isEmpty()
&& !Strings.isNullOrEmpty(nextPageToken));
PHP
$target = null;
$response = null;
$pageToken = null;
do {
// Create and execute the report list request.
$response = $this->service->reports->listReports(
$userProfileId,
['pageToken' => $pageToken]
);
foreach ($response->getItems() as $report) {
if ($this->isTargetReport($report)) {
$target = $report;
break;
}
}
$pageToken = $response->getNextPageToken();
} while (empty($target) && !empty($response->getItems()) && !empty($pageToken));
Python
target = None
# Construct the request.
request = service.reports().list(profileId=profile_id)
while True:
response = request.execute()
for report in response['items']:
if is_target_report(report):
target = report
break
if not target and response['items'] and response['nextPageToken']:
request = service.reports().list_next(request, response)
else:
break
Ruby
page_token = nil
target = nil
loop do
result = service.list_reports(profile_id, page_token: page_token)
result.items.each do |report|
if target_report?(report)
target = report
break
end
end
page_token = (result.next_page_token if target.nil? && result.items.any?)
break if page_token.to_s.empty?
end
يمكنك الرجوع إلى المستندات المرجعية للاطّلاع على المَعلمات الاختيارية التي يمكنك تحديدها للتحكّم في كيفية ترتيب وترتيب قائمة التقارير المعروضة. يمكن أن يكون التحكم في ترتيب هذه القائمة وترتيبها مفيدًا بشكل خاص للعثور على التقارير التي تم تعديلها مؤخرًا.
تشغيل تقرير
عند العثور على تقرير مناسب، يمكنك استخدام خدمة التقارير لتشغيله وإنشاء ملف تقرير جديد. يمكن تشغيل التقارير بشكلٍ متزامن أو غير متزامن (تلقائيًا)، حسب مدى تعقيد التقرير والوقت المُستغرَق في المعالجة. راجع دليل التقارير المتزامنة للحصول على تفاصيل حول إعداد التقارير المتزامنة في مقابل التقارير غير المتزامنة.
لتشغيل تقرير، يمكنك إجراء استدعاء إلى طريقة تنفيذ خدمة إعداد التقارير، كما في المثال أدناه:
#C
// Run the report.
File file = service.Reports.Run(profileId, reportId).Execute();
Java
// Run the report.
File file = reporting.reports().run(profileId, reportId).execute();
PHP
// Run the report.
$file = $this->service->reports->run($userProfileId, $reportId);
Python
# Run the report.
report_file = service.reports().run(
profileId=profile_id, reportId=report_id).execute()
Ruby
# Run the report.
report_file = service.run_report(profile_id, report_id)
الرد على هذا الطلب هو مورد الملفات. إذا كان هذا طلب تشغيل متزامن ناجحًا، سيتم ملء جميع حقول المورد المعروض وسيكون الملف جاهزًا للتنزيل. ولأنّ هذا كان طلب تشغيل غير متزامن، لن تتوفّر بعض الحقول الرئيسية وسيتم ضبط قيمة status
للملف على PROCESSING
، لأنّ تشغيل التقرير لم ينتهِ بعد.
متى يتم الانتهاء من إنشاء التقرير؟
عند تشغيل تقرير بشكل غير متزامن، يتم إنشاء ملف عنصر نائب فورًا ويتم وضع التقرير في قائمة انتظار لمعالجته. سيحتوي العنصر النائب على معلومات أساسية لمساعدتك في تحديد وقت الانتهاء من تشغيل التقرير:
- حقل
id
، يمكن استخدامه للإشارة إلى هذا الملف في الطلبات اللاحقة - حقل
status
يمثّل الحالة الحالية لعملية تشغيل التقرير.
لتحديد وقت الانتهاء من تشغيل أحد التقارير، يجب فحص status
للملف بشكل دوري، كما في المثال أدناه:
#C
// Wait for the report file to finish processing.
// An exponential backoff policy is used to limit retries and conserve quota.
int sleep = 0;
int startTime = GetCurrentTimeInSeconds();
do {
File file = service.Files.Get(reportId, fileId).Execute();
if ("REPORT_AVAILABLE".Equals(file.Status)) {
Console.WriteLine("File status is {0}, ready to download.", file.Status);
return;
} else if (!"PROCESSING".Equals(file.Status)) {
Console.WriteLine("File status is {0}, processing failed.", file.Status);
return;
} else if (GetCurrentTimeInSeconds() - startTime > MAX_RETRY_ELAPSED_TIME) {
Console.WriteLine("File processing deadline exceeded.");
return;
}
sleep = GetNextSleepInterval(sleep);
Console.WriteLine("File status is {0}, sleeping for {1} seconds.", file.Status, sleep);
Thread.Sleep(sleep * 1000);
} while (true);
Java
BackOff backOff =
new ExponentialBackOff.Builder()
.setInitialIntervalMillis(10 * 1000) // 10 second initial retry
.setMaxIntervalMillis(10 * 60 * 1000) // 10 minute maximum retry
.setMaxElapsedTimeMillis(60 * 60 * 1000) // 1 hour total retry
.build();
do {
File file = reporting.files().get(reportId, fileId).execute();
if ("REPORT_AVAILABLE".equals(file.getStatus())) {
// File has finished processing.
System.out.printf("File status is %s, ready to download.%n", file.getStatus());
return file;
} else if (!"PROCESSING".equals(file.getStatus())) {
// File failed to process.
System.out.printf("File status is %s, processing failed.", file.getStatus());
return null;
}
// The file hasn't finished processing yet, wait before checking again.
long retryInterval = backOff.nextBackOffMillis();
if (retryInterval == BackOff.STOP) {
System.out.println("File processing deadline exceeded.%n");
return null;
}
System.out.printf("File status is %s, sleeping for %dms.%n", file.getStatus(), retryInterval);
Thread.sleep(retryInterval);
} while (true);
PHP
// Wait for the report file to finish processing.
// An exponential backoff policy is used to limit retries and conserve
// quota.
$sleep = 0;
$startTime = time();
do {
$file = $this->service->files->get($reportId, $fileId);
if ($file->getStatus() === 'REPORT_AVAILABLE') {
printf('File status is %s, ready to download<br>', $file->getStatus());
return $file;
} elseif ($file->getStatus() !== 'PROCESSING') {
printf('File status is %s, processing failed<br>', $file->getStatus());
return null;
} elseif (time() - $startTime > self::MAX_RETRY_ELAPSED_TIME) {
printf('File processing deadline exceeded<br>');
return null;
}
$sleep = $this->getNextSleepInterval($sleep);
printf(
'File status is %s, sleeping for %d seconds<br>',
$file->getStatus(),
$sleep
);
$this->sleep($sleep);
} while (true);
Python
# Wait for the report file to finish processing.
# An exponential backoff strategy is used to conserve request quota.
sleep = 0
start_time = time.time()
while True:
report_file = service.files().get(
reportId=report_id, fileId=file_id).execute()
status = report_file['status']
if status == 'REPORT_AVAILABLE':
print 'File status is %s, ready to download.' % status
return
elif status != 'PROCESSING':
print 'File status is %s, processing failed.' % status
return
elif time.time() - start_time > MAX_RETRY_ELAPSED_TIME:
print 'File processing deadline exceeded.'
return
sleep = next_sleep_interval(sleep)
print 'File status is %s, sleeping for %d seconds.' % (status, sleep)
time.sleep(sleep)
Ruby
# Wait for the report file to finish processing.
# An exponential backoff strategy is used to conserve request quota.
interval = 0
start_time = Time.now
loop do
report_file = service.get_file(report_id, file_id)
status = report_file.status
if status == 'REPORT_AVAILABLE'
puts format('File status is %s, ready to download.', status)
break
elsif status != 'PROCESSING'
puts format('File status is %s, processing failed.', status)
break
elsif Time.now - start_time > MAX_RETRY_ELAPSED_TIME
puts 'File processing deadline exceeded.'
break
end
interval = next_sleep_interval(interval)
puts format('File status is %s, sleeping for %d seconds.', status,
interval)
sleep(interval)
end
عندما يتغيّر الرمز status
إلى REPORT_AVAILABLE
، يعني ذلك أنّ الملف جاهز للتنزيل. كما هو موضّح في المثال أعلاه، ننصحك بشدّة بتنفيذ استراتيجية تراجع شديد عند إجراء استطلاعات كهذه من أجل تحسين استخدام حصة الطلبات.