Rechercher et exécuter des rapports

Une fois que vous avez identifié ou créé un rapport qui répond à vos besoins, il est temps de générer une sortie. La sortie du rapport est stockée dans des fichiers de rapport, qui peuvent être récupérés et manipulés par programmation. Un fichier de rapport est généré à la suite de l'exécution d'un rapport.

Ce guide explique comment générer des fichiers de rapport par programmation via le service Reports.

Rechercher un rapport

Pour exécuter un rapport, vous devez connaître son ID. Si vous venez de créer ou de mettre à jour un rapport, cette valeur se trouve dans le champ id de la ressource de rapport renvoyée. Nous recommandons aux utilisateurs de stocker ces ID renvoyés pour les retrouver ultérieurement.

Si vous ne connaissez pas l'ID du rapport que vous souhaitez exécuter, vous pouvez parcourir la liste de tous les rapports disponibles pour trouver celui que vous recherchez. L'exemple ci-dessous montre comment rechercher un rapport à l'aide de critères définis par l'utilisateur :

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

Consultez la documentation de référence pour connaître les paramètres facultatifs que vous pouvez spécifier afin de contrôler le tri et l'ordre de la liste des rapports renvoyés. Contrôler le tri et l'ordre de cette liste peut être particulièrement utile pour trouver les rapports qui ont été modifiés récemment.

Exécuter un rapport

Une fois que vous avez trouvé un rapport approprié, vous pouvez utiliser le service Report pour l'exécuter et générer un fichier de rapport. Les rapports peuvent être exécutés de manière synchrone ou asynchrone (par défaut), en fonction de leur complexité et du temps nécessaire à leur traitement. Pour en savoir plus sur les rapports synchrones et asynchrones, consultez le guide sur les rapports synchrones.

Pour générer un rapport, vous devez appeler la méthode run du service Report, comme dans l'exemple ci-dessous :

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)

La réponse à cette requête est une ressource Files. S'il s'agissait d'une requête d'exécution synchrone réussie, tous les champs de la ressource renvoyée seraient renseignés et le fichier serait prêt à être téléchargé. Toutefois, comme il s'agissait d'une requête d'exécution asynchrone, certains champs clés seront manquants et le status du fichier sera défini sur PROCESSING, car le rapport n'a pas encore terminé son exécution.

Quand un rapport a-t-il terminé son exécution ?

Lorsque vous exécutez un rapport de manière asynchrone, un fichier espace réservé est généré immédiatement et le rapport est placé dans une file d'attente pour être traité. L'espace réservé contient deux informations clés pour vous aider à déterminer quand le rapport a terminé son exécution :

  1. Un champ id, qui peut être utilisé pour référencer ce fichier dans les requêtes suivantes.
  2. Un champ status, qui représente l'état actuel de l'exécution du rapport.

Pour déterminer quand un rapport a terminé son exécution, vous devez vérifier régulièrement le status du fichier, comme dans l'exemple ci-dessous :

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

Lorsque le status passe à REPORT_AVAILABLE, le fichier est prêt à être téléchargé. Comme indiqué dans l'exemple ci-dessus, nous vous recommandons vivement d'implémenter une stratégie d'intervalle exponentiel entre les tentatives lorsque vous effectuez des requêtes de ce type, afin d'optimiser l'utilisation de votre quota de requêtes.