Create and read a report

Learn how to create a App Optimize API report of your Google Cloud spending, monitor the report's generation, and read the resulting data when it is ready for you. In this quickstart guide, you can use the REST API or the Python client library.

Before you begin

  • The examples in this guide require a Google Cloud project with active resources to analyze. App Optimize API needs billing and utilization data to produce meaningful results; reports run against new or empty projects will be empty.

    In this guide, the project identified as PROJECT_ID provides the data scope and hosts the report resource.

    App Optimize API does support creating reports in one project that analyzes data from another project or from applications in single-project or folder-level boundaries. To generate a report on an App Hub application, which can be made up of multiple projects, you must have the required monitoring and billing permissions on all of the application's associated projects to create the report.

  • Ensure that the App Optimize API is enabled for the project you will use to create and manage the report resource.

gcloud

In the Google Cloud console, activate Cloud Shell.

Activate Cloud Shell

At the bottom of the Google Cloud console, a Cloud Shell session starts and displays a command-line prompt. Cloud Shell is a shell environment with the Google Cloud CLI already installed and with values already set for your current project. It can take a few seconds for the session to initialize.

For information about setting up authentication for a production environment, see Set up Application Default Credentials for code running on Google Cloud in the Google Cloud authentication documentation.

Python

  1. Install the Python client library for App Optimize API.
  2. To use the Python samples on this page in a local development environment, install and initialize the gcloud CLI, and then set up Application Default Credentials with your user credentials.

    1. Install the Google Cloud CLI.

    2. If you're using an external identity provider (IdP), you must first sign in to the gcloud CLI with your federated identity.

    3. If you're using a local shell, then create local authentication credentials for your user account:

      gcloud auth application-default login

      You don't need to do this if you're using Cloud Shell.

      If an authentication error is returned, and you are using an external identity provider (IdP), confirm that you have signed in to the gcloud CLI with your federated identity.

    For more information, see Set up ADC for a local development environment in the Google Cloud authentication documentation.

    For information about setting up authentication for a production environment, see Set up Application Default Credentials for code running on Google Cloud in the Google Cloud authentication documentation.

REST

To use the REST API samples on this page in a local development environment, you use the credentials you provide to the gcloud CLI.

    Install the Google Cloud CLI.

    If you're using an external identity provider (IdP), you must first sign in to the gcloud CLI with your federated identity.

For more information, see Authenticate for using REST in the Google Cloud authentication documentation.

For information about setting up authentication for a production environment, see Set up Application Default Credentials for code running on Google Cloud in the Google Cloud authentication documentation.

Required roles

To get the permissions that you need to create and read a report using this quickstart, ask your administrator to grant you the following IAM roles on your project with active resources:

  • App Optimize Admin (roles/appoptimize.admin)
  • Viewer (roles/viewer) (or another role granting billing.resourceCosts.get)

For more information about granting roles, see Manage access to projects, folders, and organizations.

You might also be able to get the required permissions through custom roles or other predefined roles.

For more information about permissions and roles required for App Optimize API, see Access control with IAM.

Create a report

This example creates a report of the total spending within your chosen PROJECT_ID. The report breaks down the costs by each Google Cloud product used, such as Compute Engine and Cloud Storage, and by the specific SKU and location. The report covers the last three days of data.

To create the report resource, follow the instructions for your preferred method:

gcloud

Use the gcloud beta app-optimize reports create command to create the report.

gcloud beta app-optimize reports create REPORT_ID \
  --project=PROJECT_ID \
  --location=global \
  --dimensions=location,product_display_name,project,sku \
  --metrics=cost \
  --report-filter='hour >= now - duration("72h")' \
  --scopes=project=projects/PROJECT_ID

Replace the following:

  • PROJECT_ID: your Google Cloud project ID.
  • REPORT_ID: a unique ID for your new report—for example, my-first-report

The command waits for the report creation operation to complete and then returns the created report resource.

Python

The following Python code uses AppOptimizeClient.create_report() to create a report.

from google.cloud import appoptimize_v1beta

project_id = "PROJECT_ID"
report_id = "REPORT_ID"

# Create the App Optimize client and prepare a request for a new report
client = appoptimize_v1beta.AppOptimizeClient()
report = appoptimize_v1beta.Report(
    dimensions=['location', 'product_display_name', 'project', 'sku'],
    metrics=['cost'],
    filter='hour >= now - duration("72h")',
    scopes=[
        appoptimize_v1beta.Scope(project=f"projects/{project_id}"),
    ],
)
request = appoptimize_v1beta.CreateReportRequest(
    parent=f"projects/{project_id}/locations/global",
    report=report,
    report_id=report_id,
)

# Request the creation of the report and wait until the process is done
operation = client.create_report(request=request)
print("Waiting for report creation operation to complete...")
response = operation.result()
print(response)

Replace the following:

  • PROJECT_ID: your Google Cloud project ID.
  • REPORT_ID: a unique ID for your new report—for example, my-first-report.

The operation.result() method waits for the report creation operation to complete.

REST

Send an HTTP POST request to the REST API's projects.locations.reports resource path.

  1. To send the request, use the following curl command:

    curl -X POST -H "Authorization: Bearer $(gcloud auth print-access-token)" \
      -H "Content-Type: application/json" \
      -d '{
        "scopes": [
          {
            "project": "projects/PROJECT_ID"
          }
        ],
        "dimensions": [
          "location",
          "product_display_name",
          "project",
          "sku"
        ],
        "metrics": [
          "cost"
        ],
        "filter": "hour >= now - duration(\"72h\")"
      }' \
      "https://appoptimize.googleapis.com/v1beta/projects/PROJECT_ID/locations/global/reports?report_id=REPORT_ID"
    

    Replace the following:

    • PROJECT_ID: your Google Cloud project ID.
    • REPORT_ID: a unique ID for your new report—for example, my-first-report

    The API returns a Long-Running Operation (LRO) object, which represents the report generation process. Here is an example response:

    {
      "name": "projects/PROJECT_ID/locations/global/operations/OPERATION_ID",
      "metadata": {
        "@type": "type.googleapis.com/google.cloud.appoptimize.v1beta.OperationMetadata"
      },
      "done": false
    }
    

    The "done": false status indicates that the report is still being generated. Note the OPERATION_ID as you will use this in the next step.

  2. Because report generation can take time, you need to poll the LRO until it indicates that the generation process is complete and the report's data is ready for download.

    To check the status of the generation process, send an HTTP GET request to the operation's resource name:

    curl -H "Authorization: Bearer $(gcloud auth print-access-token)" \
      "https://appoptimize.googleapis.com/v1beta/projects/PROJECT_ID/locations/global/operations/OPERATION_ID"
    

    Examine the response. If "done" is false, wait 5 to 15 seconds and repeat this step. If "done" is true, then the report is ready.

    The following is an example of a response when the operation is complete:

    {
      "name": "projects/PROJECT_ID/locations/global/operations/OPERATION_ID",
      "metadata": {
        "@type": "type.googleapis.com/google.cloud.appoptimize.v1beta.OperationMetadata"
      },
      "done": true,
      "response": {
        "@type": "type.googleapis.com/google.cloud.appoptimize.v1beta.Report",
        "name": "projects/PROJECT_ID/locations/global/reports/REPORT_ID",
        "scopes": [
          {
            "project": "projects/PROJECT_ID"
          }
        ],
        "dimensions": [
          "location",
          "product_display_name",
          "project",
          "sku"
        ],
        "metrics": [
          "cost"
        ],
        "filter": "hour >= now - duration(\"72h\")",
        "expireTime": "2026-02-04T22:05:05Z"
      }
    }
    

Read the report data

To retrieve the report data, follow the instructions for your preferred method:

gcloud

Use the following gcloud beta app-optimize reports read command to fetch the report's data.

gcloud beta app-optimize reports read REPORT_ID \
  --project=PROJECT_ID \
  --location=global

Python

The following Python code uses AppOptimizeClient.read_report() to fetch the report's data.

from google.cloud import appoptimize_v1beta

project_id = "PROJECT_ID"
report_id = "REPORT_ID"
name = f"projects/{project_id}/locations/global/reports/{report_id}"

# Create the App Optimize client and read your report's data
client = appoptimize_v1beta.AppOptimizeClient()
request = appoptimize_v1beta.ReadReportRequest(
        name=name,
)
result = client.read_report(request=request)

# Display the report's data
print(result)

REST

Once the LRO is complete, use the REST API's :read custom method:

curl -X POST \
  -H "Authorization: Bearer $(gcloud auth print-access-token)" \
  -H "Content-Type: application/json" \
  -d '{}' \
  "https://appoptimize.googleapis.com/v1beta/projects/PROJECT_ID/locations/global/reports/REPORT_ID:read"

The response from the API contains the report data rows and column definitions. The following is an example of a successful response:

{
  "rows": [
    [
      "us-central1",
      "Compute Engine",
      "projects/PROJECT_ID",
      "6EC2-384A-47D9",
      {
        "currency_code": "USD",
        "units": "25",
        "nanos": 750000000
      }
    ],
    [
      "us-central1",
      "Cloud Storage",
      "projects/PROJECT_ID",
      "9ADA-9ADC-2FBE",
      {
        "currency_code": "USD",
        "units": "5",
        "nanos": 100000000
      }
    ],
    [
      "europe-west1",
      "Compute Engine",
      "projects/PROJECT_ID",
      "6EC2-384A-47D9",
      {
        "currency_code": "USD",
        "units": "18",
        "nanos": 500000000
      }
    ],
    [
      "us-central1",
      "Compute Engine",
      "projects/PROJECT_ID",
      "F61D-4D51-AAFC",
      {
        "currency_code": "USD",
        "units": "12",
        "nanos": 200000000
      }
    ]
  ],
  "columns": [
    {
      "name": "location",
      "type": "STRING",
      "mode": "NULLABLE"
    },
    {
      "name": "product_display_name",
      "type": "STRING",
      "mode": "NULLABLE"
    },
    {
      "name": "project",
      "type": "STRING",
      "mode": "NULLABLE"
    },
    {
      "name": "sku",
      "type": "STRING",
      "mode": "NULLABLE"
    },
    {
      "name": "cost",
      "type": "RECORD",
      "mode": "NULLABLE",
      "columns": [
        {
          "name": "currency_code",
          "type": "STRING",
          "mode": "NULLABLE"
        },
        {
          "name": "units",
          "type": "INT64",
          "mode": "NULLABLE"
        },
        {
          "name": "nanos",
          "type": "INT64",
          "mode": "NULLABLE"
        }
      ]
    }
  ],
  "next_page_token": ""
}

Reports with many rows are paginated. To handle multiple pages, see Read a report's data.

To understand the values in the cost field, see Interpreting cost metrics. For more information on the data and to understand its limitations, see Understanding the data.

Clean up

App Optimize API automatically deletes your report 24 hours after it is created. To delete the report sooner, follow the instructions for your preferred method:

gcloud

Use the gcloud beta app-optimize reports delete command to remove the report.

gcloud beta app-optimize reports delete REPORT_ID \
  --project=PROJECT_ID \
  --location=global

Python

The following code uses AppOptimizeClient.delete_report() to remove the report.

from google.cloud import appoptimize_v1beta

project_id = "PROJECT_ID"
report_id = "REPORT_ID"

name = f"projects/{project_id}/locations/global/reports/{report_id}"
client = appoptimize_v1beta.AppOptimizeClient()
request = appoptimize_v1beta.DeleteReportRequest(name=name)
client.delete_report(request=request)
print(f"Deleted report: {name}")

REST

Send an HTTP DELETE request to the report's resource endpoint:

curl -X DELETE \
  -H "Authorization: Bearer $(gcloud auth print-access-token)" \
  "https://appoptimize.googleapis.com/v1beta/projects/PROJECT_ID/locations/global/reports/REPORT_ID"

What's next