Gdy znajdziesz lub utworzysz raport, który spełnia Twoje potrzeby, możesz wygenerować dane wyjściowe. Dane wyjściowe raportu są przechowywane w plikach raportu, które można pobrać i przetwarzać programowo. Plik raportu jest tworzony w wyniku wygenerowania raportu.
Z tego przewodnika dowiesz się, jak programowo generować pliki raportu za pomocą usługi Reports.
Znajdowanie raportu
Aby wygenerować raport, musisz znać jego identyfikator. Jeśli raport został właśnie utworzony lub zaktualizowany, tę wartość znajdziesz w polu id zwróconego zasobu raportu. Zalecamy, aby użytkownicy przechowywali te zwrócone identyfikatory na potrzeby późniejszego wyszukiwania.
Jeśli nie znasz identyfikatora raportu, który chcesz wygenerować, możesz przejrzeć listę wszystkich dostępnych raportów, aby znaleźć odpowiedni. Poniższy przykład pokazuje, jak wyszukać raport według określonych przez użytkownika kryteriów:
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=str(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
W dokumentacji znajdziesz informacje o opcjonalnych parametrach, które możesz określić, aby kontrolować sortowanie i kolejność zwracanych raportów. Kontrolowanie sortowania i kolejności tej listy może być szczególnie przydatne do znajdowania raportów, które zostały niedawno zmodyfikowane.
Wygeneruj raport
Gdy znajdziesz odpowiedni raport, możesz użyć usługi Report, aby go stosować i wygenerować nowy plik raportu. Raporty można generować synchronicznie lub asynchronicznie (domyślnie) w zależności od złożoności raportu i czasu potrzebnego na jego przetworzenie. Więcej informacji o raportowaniu synchronicznym i asynchronicznym znajdziesz w przewodniku po raportach synchronicznych.
Aby wygenerować raport, wywołaj metodę run usługi Report, jak w poniższym przykładzie:
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=str(profile_id), reportId=str(report_id))
.execute()
)
Ruby
# Run the report.
report_file = service.run_report(profile_id, report_id)
Odpowiedzią na to żądanie jest zasób Files. Jeśli byłoby to udane synchroniczne żądanie wygenerowania, wszystkie pola zwróconego zasobu byłyby wypełnione, a plik byłby gotowy do pobrania. Ponieważ było to jednak asynchroniczne żądanie wygenerowania, niektóre kluczowe pola będą puste, a stan pliku zostanie ustawiony na PROCESSING, ponieważ raport nie został jeszcze wygenerowany.status
Kiedy raport jest gotowy?
Gdy wygenerujesz raport asynchronicznie, natychmiast zostanie utworzony plik zastępczy, a raport zostanie umieszczony w kolejce do przetworzenia. Plik zastępczy będzie zawierać 2 kluczowe informacje, które pomogą Ci określić, kiedy raport zostanie wygenerowany:
- Pole
id, którego można użyć do odwoływania się do tego pliku w kolejnych żądaniach. - Pole
status, które reprezentuje bieżący stan generowania raportu.
Aby określić, kiedy raport zostanie wygenerowany, musisz okresowo sprawdzać status pliku, jak w poniższym przykładzie:
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=str(report_id), fileId=str(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
Gdy wartość status zmieni się na REPORT_AVAILABLE, plik będzie gotowy do pobrania. Jak pokazano w powyższym przykładzie, zdecydowanie zalecamy wdrożenie strategii wzrastającego czasu do ponowienia podczas takiego sondowania, aby zoptymalizować wykorzystanie limitu żądań.