گزارش ها را پیدا و اجرا کنید

پس از شناسایی یا ایجاد گزارشی که نیازهای شما را برآورده می‌کند، زمان تولید خروجی فرا می‌رسد. خروجی گزارش در فایل‌های گزارش ذخیره می‌شود که می‌توان آنها را به صورت برنامه‌نویسی بازیابی و دستکاری کرد. یک فایل گزارش در نتیجه اجرای یک گزارش تولید می‌شود.

این راهنما جزئیات نحوه تولید فایل‌های گزارش از طریق سرویس 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));

پی اچ پی

$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=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

روبی

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 از سرویس Report را فراخوانی می‌کنید، مانند مثال زیر:

سی شارپ

// Run the report.
File file = service.Reports.Run(profileId, reportId).Execute();

جاوا

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

پی اچ پی

// Run the report.
$file = $this->service->reports->run($userProfileId, $reportId);

پایتون

# Run the report.
report_file = (
    service.reports()
    .run(profileId=str(profile_id), reportId=str(report_id))
    .execute()
)

روبی

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

پاسخ به این درخواست یک منبع Files است. اگر این یک درخواست اجرای همزمان موفق بود، تمام فیلدهای منبع برگردانده شده پر می‌شدند و فایل آماده دانلود می‌شد. با این حال، از آنجایی که این یک درخواست اجرای غیرهمزمان بود، برخی از فیلدهای کلیدی وجود نخواهند داشت و status فایل روی PROCESSING تنظیم می‌شود، زیرا اجرای گزارش هنوز به پایان نرسیده است.

چه زمانی اجرای یک گزارش تمام می‌شود؟

وقتی یک گزارش را به صورت غیرهمزمان اجرا می‌کنید، یک فایل placeholder بلافاصله ایجاد می‌شود و گزارش برای پردازش در صف قرار می‌گیرد. placeholder شامل دو بخش کلیدی از اطلاعات است که به شما کمک می‌کند زمان پایان اجرای گزارش را تعیین کنید:

  1. یک فیلد id که می‌تواند برای ارجاع به این فایل در درخواست‌های بعدی استفاده شود.
  2. یک فیلد 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);

پی اچ پی

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

روبی

# 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 تغییر می‌کند، فایل آماده دانلود است. همانطور که در مثال بالا نشان داده شده است، اکیداً توصیه می‌شود که هنگام نمونه‌برداری مانند این، یک استراتژی backoff نمایی پیاده‌سازی کنید تا میزان استفاده از سهمیه درخواست خود را بهینه کنید.