После того, как вы определили или создали отчет, который удовлетворяет вашим потребностям, пришло время генерировать выходные данные. Выходные данные отчета хранятся в файлах отчетов, которые можно извлекать и обрабатывать программно. Файл отчета создается в результате выполнения отчета.
В этом руководстве подробно описано, как программно генерировать файлы отчетов с помощью службы Reports .
Найти отчет
Чтобы запустить отчет, вам нужно знать идентификатор отчета. Если вы только что создали или обновили отчет , это значение можно найти в поле id
возвращенного ресурса отчета. Пользователям рекомендуется сохранять эти возвращенные идентификаторы для последующего поиска.
Если вы не знаете идентификатор отчета, который хотите запустить, вы можете просмотреть список всех доступных отчетов, чтобы найти нужный. В приведенном ниже примере показано, как искать отчет по определенным пользователем критериям:
С#
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));
Джава
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));
Питон
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
Рубин
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
Обратитесь к справочной документации за необязательными параметрами, которые можно указать для управления сортировкой и порядком списка возвращаемых отчетов. Управление сортировкой и порядком в этом списке может быть особенно полезно для поиска недавно измененных отчетов.
Запустить отчет
Найдя подходящий отчет, вы можете использовать службу отчетов, чтобы запустить его и создать новый файл отчета. Отчеты могут запускаться синхронно или асинхронно (по умолчанию), в зависимости от сложности отчета и времени, которое потребуется для его обработки. Подробнее о синхронных и асинхронных отчетах см. в руководстве по синхронным отчетам.
Чтобы запустить отчет, вы вызываете метод run службы отчетов, как в примере ниже:
С#
// Run the report.
File file = service.Reports.Run(profileId, reportId).Execute();
Джава
// Run the report.
File file = reporting.reports().run(profileId, reportId).execute();
PHP
// Run the report.
$file = $this->service->reports->run($userProfileId, $reportId);
питон
# Run the report.
report_file = service.reports().run(
profileId=profile_id, reportId=report_id).execute()
Рубин
# Run the report.
report_file = service.run_report(profile_id, report_id)
Ответом на этот запрос является ресурс Files . Если бы это был успешный запрос синхронного запуска, все поля возвращаемого ресурса были бы заполнены, и файл был бы готов к загрузке. Однако, поскольку это был асинхронный запрос на выполнение, некоторые ключевые поля будут отсутствовать, а status
файла будет установлен на PROCESSING
, так как отчет еще не завершен.
Когда отчет закончен?
При асинхронном запуске отчета немедленно создается файл-заполнитель, и отчет помещается в очередь для обработки. Заполнитель будет содержать две ключевые части информации, которые помогут вам определить, когда отчет будет завершен:
- Поле
id
, которое можно использовать для ссылки на этот файл в последующих запросах. - Поле
status
, которое представляет текущее состояние выполнения отчета.
Чтобы определить, когда отчет завершен, вам необходимо периодически проверять status
файла, как в примере ниже:
С#
// 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);
Джава
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);
питон
# 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)
Рубин
# 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
, файл готов к загрузке. Как показано в приведенном выше примере, настоятельно рекомендуется реализовать экспоненциальную стратегию отсрочки при подобном опросе, чтобы оптимизировать использование квоты запросов .