Znajdowanie i uruchamianie raportów

Po wybraniu lub utworzeniu raportu, który odpowiada Twoim potrzebom, możesz wygenerować dane wyjściowe. Wyniki są przechowywane w plikach raportów, które można pobierać i zmieniać automatycznie. Plik raportu jest tworzony w wyniku wygenerowania raportu.

Ten przewodnik zawiera szczegółowe informacje na temat automatycznego generowania plików raportów przy użyciu usługi Raporty.

Znajdowanie raportu

Aby wygenerować raport, musisz znać jego identyfikator. Jeśli raport został właśnie utworzony lub zaktualizowany, znajdziesz tę wartość w polu id w zwróconym zasobie raportu. Zalecamy przechowywanie tych zwróconych identyfikatorów na potrzeby późniejszego wyszukiwania.

Jeśli nie wiesz, jaki identyfikator raportu chcesz wygenerować, możesz przejrzeć listę dostępnych raportów, by znaleźć ten, który Cię interesuje. Przykład poniżej pokazuje, jak znaleźć raport według kryteriów zdefiniowanych przez użytkownika:

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

W dokumentacji referencyjnej znajdziesz parametry opcjonalne, które możesz ustawić w celu kontrolowania sposobu sortowania i porządkowania listy zwracanych raportów. Kontrola sortowania i sortowania tej listy może być szczególnie przydatna, jeśli chcesz znaleźć ostatnio zmodyfikowane raporty.

Generowanie raportu

Gdy znajdziesz odpowiedni raport, możesz go użyć do wygenerowania raportu i wygenerowania nowego pliku. Raporty mogą być generowane synchronicznie lub asynchronicznie (domyślnie), w zależności od złożoności raportu i czasu na przygotowanie raportu. Szczegółowe informacje o raportach synchronicznych i asynchronicznych znajdziesz w przewodniku po raportach synchronicznych.

Aby wygenerować raport, musisz wywołać metodę generowania usługi Raport, jak w tym 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=profile_id, reportId=report_id).execute()

Ruby

# Run the report.
report_file = service.run_report(profile_id, report_id)

Odpowiedź na to żądanie to zasób Files. Jeśli to udane synchroniczne żądanie uruchomienia, wszystkie pola zwróconego zasobu zostaną wypełnione i plik będzie gotowy do pobrania. Ponieważ było to asynchroniczne żądanie uruchomienia, niektóre kluczowe pola będą niekompletne, a zasada status pliku zostanie ustawiona na PROCESSING, bo raport nie został jeszcze wygenerowany.

Kiedy generowany jest raport?

Gdy raport jest generowany asynchronicznie, plik zastępczy jest generowany natychmiast i trafia do kolejki do przetworzenia. Będzie on zawierać 2 kluczowe informacje, które pomogą Ci określić, kiedy raport będzie gotowy:

  1. Pole id, którego można użyć do odwoływania się do tego pliku w kolejnych żądaniach.
  2. Pole status, które reprezentuje bieżący stan generowania raportu.

Aby określić, kiedy raport był gotowy, należy co jakiś czas sprawdzać plik status, jak w tym 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=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

Gdy status zmieni się na REPORT_AVAILABLE, plik będzie gotowy do pobrania. Jak pokazano w przykładzie powyżej, przy implementowaniu takich ankiet zdecydowanie zalecamy zastosowanie wykładniczej metody ponowienia, aby zoptymalizować wykorzystanie żądań.