보고서 찾기 및 실행

니즈를 충족하는 보고서를 파악하거나 만들었으면 이제 출력을 생성해야 합니다. 보고서 출력은 보고서 파일에 저장되어 프로그래매틱 방식으로 검색하고 조작할 수 있습니다. 보고서 파일은 보고서 실행의 결과로 생성됩니다.

이 가이드에서는 보고서 서비스를 통해 프로그래매틱 방식으로 보고서 파일을 생성하는 방법을 자세히 설명합니다.

보고서 찾기

보고서를 실행하려면 보고서의 ID를 알아야 합니다. 보고서를 만들거나 업데이트한 경우 반환된 보고서 리소스의 id 필드에서 이 값을 찾을 수 있습니다. 나중에 조회할 수 있도록 반환된 ID를 저장하는 것이 좋습니다.

실행하려는 보고서 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));

자바

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));

2,399필리핀

$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();

자바

// Run the report.
File file = reporting.reports().run(profileId, reportId).execute();

2,399필리핀

// 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)

이 요청에 대한 응답은 파일 리소스입니다. 동기식 실행 요청이 성공하면 반환된 리소스의 모든 필드가 채워지고 파일을 다운로드할 수 있게 됩니다. 하지만 비동기식 실행 요청이므로 특정 키 필드가 누락되고 파일의 statusPROCESSING로 설정됩니다. 보고서 실행이 아직 완료되지 않았기 때문입니다.

보고서 실행은 언제 완료되나요?

보고서를 비동기식으로 실행하면 자리표시자 파일이 즉시 생성되며 보고서가 처리를 위해 대기열에 추가됩니다. 자리표시자에는 보고서 실행이 완료되는 시점을 확인하는 데 도움이 되는 두 가지 주요 정보가 포함됩니다.

  1. id 필드: 후속 요청에서 이 파일을 참조하는 데 사용할 수 있습니다.
  2. 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);

자바

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);

2,399필리핀

// 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

statusREPORT_AVAILABLE로 변경되면 파일을 다운로드할 수 있습니다. 위의 예에 나와 있는 것처럼, 이와 같이 폴링하는 경우 지수 백오프 전략을 구현하여 요청 할당량 사용을 최적화하는 것이 좋습니다.