Reading metric data

This document explains how to read metric data, also called time-series data, using the timeSeries.list method in the Monitoring API.

This document doesn't discuss Monitoring Query Language (MQL) and the timeSeries.query method. For that information, see Using MQL from the Monitoring API.

There are several ways to use the timeSeries.list method:

  • To run the list method without writing any code, the examples in the PROTOCOL tabs on this page use the forms-based APIs Explorer. (See APIs Explorer for more information on this tool.)

  • To learn how to use the list method from selected programming languages, see the runnable code samples on this page. There is no Cloud SDK support for using the gcloud command-line tool to read metric data.

  • To view the metrics for a monitored resource using Metrics Explorer, do the following:

    1. In the Google Cloud Console, go to Monitoring or use the following button:
      Go to Monitoring
    2. In the Monitoring navigation pane, click Metrics Explorer.
    3. Select the Configuration tab, and then enter or select a Resource type and a Metric.

For an introduction to metrics and time series, see Metrics, time series, and resources.

Overview

Each call to the timeSeries.list method can return any number of time series from a single metric type. For example, if you are using Compute Engine, then the compute.googleapis.com/instance/cpu/usage_time metric type has a separate time series for each of your VM instances.

You specify which time series data you want by supplying the following:

  • A filter expression that specifies the metric type. Optionally, the filter selects a subset of the metric's time series by specifying the resources producing the time series or specifying values for certain labels in the time series.
  • A time interval that limits how much data is returned.
  • Optionally, a specification of how to combine multiple time series to produce an aggregate summary of the data. For more information, see Aggregating data for some examples.

Time-series filters

You specify which time series to retrieve by passing a time-series filter to the timeSeries.list method. The following lists the common filter components:

  • The filter must specify a single metric type. For example:

    metric.type = "compute.googleapis.com/instance/cpu/usage_time"
    

    To retrieve custom metrics, change the metric.type prefix in the filter to custom.googleapis.com or another prefix if used; external.googleapis.com is frequently used.

  • The filter can specify values for the metric's dimension labels. The metric type determines which labels are present. For example:

    (metric.label.instance_name = "your-instance-id" OR
      metric.label.instance_name = "your-other-instance-id")
    

    In the previous expression, label is correct even though the actual metric object uses labels as its key.

  • The filter can select only those time series that contain a specific monitored resource type:

    resource.type = "gae_app"
    

The filter components can be combined into a single time series filter, such as the following:

metric.type = "compute.googleapis.com/instance/cpu/usage_time"
AND (metric.label.instance_name = "your-instance-id" OR
  metric.label.instance_name = "your-other-instance-id")

If you don't specify values for all metric labels, then the list method returns a time series for each combination of values in the unspecified labels. The method returns only time series that have data.

Time intervals

When you use the API to read data, you specify the time interval for which you want to retrieve data by setting start and end times. The API retrieves data from the interval (start, end], that is, from after the start time through the end time.

The start time must be no later than the end time. If you specify a start time that is later than the end time, then the API returns an error.

If you want to retrieve only data with a specific timestamp, then set the start time equal to the end time, or equivalently, don't set the start time.

Time format

Start and end times must be specified as strings in RFC 3339 format. For example:

2021-09-01T12:34:56+04:00
2021-09-01T12:34:56.992Z

The date -Iseconds command on Linux is useful for generating timestamps.

Basic list operations

The timeSeries.list method can be used to return simple, raw data, or it can be used to return highly processed data. This section illustrates some basic uses.

Example: Listing available time series

This example shows how to list only the names and descriptions of the time series that match a filter, rather than returning all the available data:

Protocol

Here are the sample parameters to timeSeries.list:

  • name: projects/PROJECT_ID
  • filter: metric.type = "compute.googleapis.com/instance/cpu/utilization"
  • interval.startTime: 2021-09-01T00:00:00Z
  • interval.endTime: 2021-09-01T00:20:00Z
  • fields: timeSeries.metric

    To access the fields parameter, click Show standard parameters.

Try It!

Before clicking the Execute button, change PROJECT_ID to your ID of your project, and set the end time to something recent and the start time to 20 minutes earlier.

The sample output shows time series for two different VM instances:

{
  "timeSeries": [
    {
      "metric": {
        "labels": {
          "instance_name": "your-first-instance"
        },
        "type": "compute.googleapis.com/instance/cpu/utilization"
      },
    },
    {
      "metric": {
        "labels": {
          "instance_name": "your-second-instance"
        },
        "type": "compute.googleapis.com/instance/cpu/utilization"
      },
    }
  ]
}

To view the request as a cURL command, as an HTTP request, or in JavaScript, click Full screen in APIs Explorer.

C#

public static object ReadTimeSeriesFields(string projectId,
    string metricType = "compute.googleapis.com/instance/cpu/utilization")
{
    Console.WriteLine($"metricType{ metricType}");
    // Create client.
    MetricServiceClient metricServiceClient = MetricServiceClient.Create();
    // Initialize request argument(s).
    string filter = $"metric.type=\"{metricType}\"";
    ListTimeSeriesRequest request = new ListTimeSeriesRequest
    {
        ProjectName = new ProjectName(projectId),
        Filter = filter,
        Interval = new TimeInterval(),
        View = ListTimeSeriesRequest.Types.TimeSeriesView.Headers,
    };
    // Create timestamp for current time formatted in seconds.
    long timeStamp = (long)(DateTime.UtcNow - s_unixEpoch).TotalSeconds;
    Timestamp startTimeStamp = new Timestamp();
    // Set startTime to limit results to the last 20 minutes.
    startTimeStamp.Seconds = timeStamp - (60 * 20);
    Timestamp endTimeStamp = new Timestamp();
    // Set endTime to current time.
    endTimeStamp.Seconds = timeStamp;
    TimeInterval interval = new TimeInterval();
    interval.StartTime = startTimeStamp;
    interval.EndTime = endTimeStamp;
    request.Interval = interval;
    // Make the request.
    PagedEnumerable<ListTimeSeriesResponse, TimeSeries> response =
        metricServiceClient.ListTimeSeries(request);
    // Iterate over all response items, lazily performing RPCs as required.
    Console.Write("Found data points for the following instances:");
    foreach (var item in response)
    {
        Console.WriteLine(JObject.Parse($"{item}").ToString());
    }
    return 0;
}

Go

import (
	"context"
	"fmt"
	"io"
	"time"

	monitoring "cloud.google.com/go/monitoring/apiv3"
	"github.com/golang/protobuf/ptypes/timestamp"
	"google.golang.org/api/iterator"
	monitoringpb "google.golang.org/genproto/googleapis/monitoring/v3"
)

// readTimeSeriesFields reads the last 20 minutes of the given metric, aligns
// everything on 10 minute intervals, and combines values from different
// instances.
func readTimeSeriesFields(w io.Writer, projectID string) error {
	ctx := context.Background()
	client, err := monitoring.NewMetricClient(ctx)
	if err != nil {
		return fmt.Errorf("NewMetricClient: %v", err)
	}
	defer client.Close()
	startTime := time.Now().UTC().Add(time.Minute * -20)
	endTime := time.Now().UTC()
	req := &monitoringpb.ListTimeSeriesRequest{
		Name:   "projects/" + projectID,
		Filter: `metric.type="compute.googleapis.com/instance/cpu/utilization"`,
		Interval: &monitoringpb.TimeInterval{
			StartTime: &timestamp.Timestamp{
				Seconds: startTime.Unix(),
			},
			EndTime: &timestamp.Timestamp{
				Seconds: endTime.Unix(),
			},
		},
		View: monitoringpb.ListTimeSeriesRequest_HEADERS,
	}
	fmt.Fprintln(w, "Found data points for the following instances:")
	it := client.ListTimeSeries(ctx, req)
	for {
		resp, err := it.Next()
		if err == iterator.Done {
			break
		}
		if err != nil {
			return fmt.Errorf("could not read time series value: %v", err)
		}
		fmt.Fprintf(w, "\t%v\n", resp.GetMetric().GetLabels()["instance_name"])
	}
	fmt.Fprintln(w, "Done")
	return nil
}

Java

MetricServiceClient metricServiceClient = MetricServiceClient.create();
String projectId = System.getProperty("projectId");
ProjectName name = ProjectName.of(projectId);

// Restrict time to last 20 minutes
long startMillis = System.currentTimeMillis() - ((60 * 20) * 1000);
TimeInterval interval =
    TimeInterval.newBuilder()
        .setStartTime(Timestamps.fromMillis(startMillis))
        .setEndTime(Timestamps.fromMillis(System.currentTimeMillis()))
        .build();

ListTimeSeriesRequest.Builder requestBuilder =
    ListTimeSeriesRequest.newBuilder()
        .setName(name.toString())
        .setFilter("metric.type=\"compute.googleapis.com/instance/cpu/utilization\"")
        .setInterval(interval)
        .setView(ListTimeSeriesRequest.TimeSeriesView.HEADERS);

ListTimeSeriesRequest request = requestBuilder.build();

ListTimeSeriesPagedResponse response = metricServiceClient.listTimeSeries(request);

System.out.println("Got timeseries headers: ");
for (TimeSeries ts : response.iterateAll()) {
  System.out.println(ts);
}

Node.js

// Imports the Google Cloud client library
const monitoring = require('@google-cloud/monitoring');

// Creates a client
const client = new monitoring.MetricServiceClient();

async function readTimeSeriesFields() {
  /**
   * TODO(developer): Uncomment and edit the following lines of code.
   */
  // const projectId = 'YOUR_PROJECT_ID';

  const request = {
    name: client.projectPath(projectId),
    filter: 'metric.type="compute.googleapis.com/instance/cpu/utilization"',
    interval: {
      startTime: {
        // Limit results to the last 20 minutes
        seconds: Date.now() / 1000 - 60 * 20,
      },
      endTime: {
        seconds: Date.now() / 1000,
      },
    },
    // Don't return time series data, instead just return information about
    // the metrics that match the filter
    view: 'HEADERS',
  };

  // Writes time series data
  const [timeSeries] = await client.listTimeSeries(request);
  console.log('Found data points for the following instances:');
  timeSeries.forEach(data => {
    console.log(data.metric.labels.instance_name);
  });
}
readTimeSeriesFields();

PHP

use Google\Cloud\Monitoring\V3\MetricServiceClient;
use Google\Cloud\Monitoring\V3\TimeInterval;
use Google\Cloud\Monitoring\V3\ListTimeSeriesRequest_TimeSeriesView;
use Google\Protobuf\Timestamp;

/**
 * Example:
 * ```
 * read_timeseries_fields($projectId);
 * ```
 *
 * @param string $projectId Your project ID
 */
function read_timeseries_fields($projectId, $minutesAgo = 20)
{
    $metrics = new MetricServiceClient([
        'projectId' => $projectId,
    ]);

    $projectName = $metrics->projectName($projectId);
    $filter = 'metric.type="compute.googleapis.com/instance/cpu/utilization"';

    $startTime = new Timestamp();
    $startTime->setSeconds(time() - (60 * $minutesAgo));
    $endTime = new Timestamp();
    $endTime->setSeconds(time());

    $interval = new TimeInterval();
    $interval->setStartTime($startTime);
    $interval->setEndTime($endTime);

    $view = ListTimeSeriesRequest_TimeSeriesView::HEADERS;

    $result = $metrics->listTimeSeries(
        $projectName,
        $filter,
        $interval,
        $view);

    printf('Found data points for the following instances:' . PHP_EOL);
    foreach ($result->iterateAllElements() as $timeSeries) {
        printf($timeSeries->getMetric()->getLabels()['instance_name'] . PHP_EOL);
    }
}

Python

from google.cloud import monitoring_v3

client = monitoring_v3.MetricServiceClient()
project_name = f"projects/{project_id}"
now = time.time()
seconds = int(now)
nanos = int((now - seconds) * 10 ** 9)
interval = monitoring_v3.TimeInterval(
    {
        "end_time": {"seconds": seconds, "nanos": nanos},
        "start_time": {"seconds": (seconds - 1200), "nanos": nanos},
    }
)
results = client.list_time_series(
    request={
        "name": project_name,
        "filter": 'metric.type = "compute.googleapis.com/instance/cpu/utilization"',
        "interval": interval,
        "view": monitoring_v3.ListTimeSeriesRequest.TimeSeriesView.HEADERS,
    }
)
for result in results:
    print(result)

Ruby

# Your Google Cloud Platform project ID
# project_id = "YOUR_PROJECT_ID"

client = Google::Cloud::Monitoring.metric_service
project_name = client.project_path project: project_id

interval = Google::Cloud::Monitoring::V3::TimeInterval.new
now = Time.now
interval.end_time = Google::Protobuf::Timestamp.new seconds: now.to_i,
                                                    nanos:   now.nsec
interval.start_time = Google::Protobuf::Timestamp.new seconds: now.to_i - 1200,
                                                      nanos:   now.nsec
filter = 'metric.type = "compute.googleapis.com/instance/cpu/utilization"'
view = Google::Cloud::Monitoring::V3::ListTimeSeriesRequest::TimeSeriesView::HEADERS

results = client.list_time_series name:     project_name,
                                  filter:   filter,
                                  interval: interval,
                                  view:     view
results.each do |result|
  p result
end

If you have difficulty, see Troubleshooting API calls.

Example: Getting time series data

This example returns all the information available to the timeSeries.list request, including the metric data, from Compute Engine instances for the last 20 minutes.

Protocol

The protocol example further limits the output, to make the returned data more manageable in the response box. This example uses different field values:

  • The filter value now limits the time series to a single VM instance.
  • The fields value now specifies only the time and value of the measurements.

These settings limit the amount of time series data returned in the result.

Here are the sample parameters to timeSeries.list:

  • name: projects/PROJECT_ID
  • filter: metric.type = "compute.googleapis.com/instance/cpu/utilization" AND metric.label.instance_name = "YOUR_INSTANCE_NAME"
  • interval.startTime: 2021-09-01T00:00:00Z
  • interval.endTime: 2021-09-01T00:20:00Z
  • fields: timeSeries.points.interval.endTime,timeSeries.points.value

    To access the fields parameter, click Show standard parameters.

Try It!

Before clicking the Execute button, change PROJECT_ID and YOUR_INSTANCE_NAME to values in your project, and set the end time to something recent and the start time to 20 minutes earlier.

The request returns a result like the following:

{
 "timeSeries": [
  {
   "points": [
    {
     "interval": {
      "endTime": "2021-09-01T00:19:01Z"
     },
     "value": {
      "doubleValue": 0.06763074536575005
     }
    },
    {
     "interval": {
      "endTime": "2021-09-01T00:18:01Z"
     },
     "value": {
      "doubleValue": 0.06886174467702706
     }
    },
    ...
    {
     "interval": {
      "endTime": "2021-09-01T00:17:01Z"
     },
     "value": {
      "doubleValue": 0.06929610064253211
     }
    }
   ]
  }
 ]
}

To view the request as a cURL command, as an HTTP request, or in JavaScript, click Full screen in APIs Explorer.

C#

public static object ReadTimeSeriesData(string projectId,
    string metricType = "compute.googleapis.com/instance/cpu/utilization")
{
    // Create client.
    MetricServiceClient metricServiceClient = MetricServiceClient.Create();
    // Initialize request argument(s).
    string filter = $"metric.type=\"{metricType}\"";
    ListTimeSeriesRequest request = new ListTimeSeriesRequest
    {
        ProjectName = new ProjectName(projectId),
        Filter = filter,
        Interval = new TimeInterval(),
        View = ListTimeSeriesRequest.Types.TimeSeriesView.Full,
    };
    // Create timestamp for current time formatted in seconds.
    long timeStamp = (long)(DateTime.UtcNow - s_unixEpoch).TotalSeconds;
    Timestamp startTimeStamp = new Timestamp();
    // Set startTime to limit results to the last 20 minutes.
    startTimeStamp.Seconds = timeStamp - (60 * 20);
    Timestamp endTimeStamp = new Timestamp();
    // Set endTime to current time.
    endTimeStamp.Seconds = timeStamp;
    TimeInterval interval = new TimeInterval();
    interval.StartTime = startTimeStamp;
    interval.EndTime = endTimeStamp;
    request.Interval = interval;
    // Make the request.
    PagedEnumerable<ListTimeSeriesResponse, TimeSeries> response =
        metricServiceClient.ListTimeSeries(request);
    // Iterate over all response items, lazily performing RPCs as required.
    foreach (TimeSeries item in response)
    {
        Console.WriteLine(JObject.Parse($"{item}").ToString());
    }
    return 0;
}

Go


// readTimeSeriesValue reads the TimeSeries for the value specified by metric type in a time window from the last 20 minutes.
func readTimeSeriesValue(projectID, metricType string) error {
	ctx := context.Background()
	c, err := monitoring.NewMetricClient(ctx)
	if err != nil {
		return err
	}
	defer c.Close()
	startTime := time.Now().UTC().Add(time.Minute * -20).Unix()
	endTime := time.Now().UTC().Unix()

	req := &monitoringpb.ListTimeSeriesRequest{
		Name:   "projects/" + projectID,
		Filter: fmt.Sprintf("metric.type=\"%s\"", metricType),
		Interval: &monitoringpb.TimeInterval{
			StartTime: &timestamp.Timestamp{Seconds: startTime},
			EndTime:   &timestamp.Timestamp{Seconds: endTime},
		},
	}
	iter := c.ListTimeSeries(ctx, req)

	for {
		resp, err := iter.Next()
		if err == iterator.Done {
			break
		}
		if err != nil {
			return fmt.Errorf("could not read time series value, %v ", err)
		}
		log.Printf("%+v\n", resp)
	}

	return nil
}

Java

MetricServiceClient metricServiceClient = MetricServiceClient.create();
String projectId = System.getProperty("projectId");
ProjectName name = ProjectName.of(projectId);

// Restrict time to last 20 minutes
long startMillis = System.currentTimeMillis() - ((60 * 20) * 1000);
TimeInterval interval =
    TimeInterval.newBuilder()
        .setStartTime(Timestamps.fromMillis(startMillis))
        .setEndTime(Timestamps.fromMillis(System.currentTimeMillis()))
        .build();

ListTimeSeriesRequest.Builder requestBuilder =
    ListTimeSeriesRequest.newBuilder()
        .setName(name.toString())
        .setFilter(filter)
        .setInterval(interval);

ListTimeSeriesRequest request = requestBuilder.build();

ListTimeSeriesPagedResponse response = metricServiceClient.listTimeSeries(request);

System.out.println("Got timeseries: ");
for (TimeSeries ts : response.iterateAll()) {
  System.out.println(ts);
}

Node.js

// Imports the Google Cloud client library
const monitoring = require('@google-cloud/monitoring');

// Creates a client
const client = new monitoring.MetricServiceClient();

async function readTimeSeriesData() {
  /**
   * TODO(developer): Uncomment and edit the following lines of code.
   */
  // const projectId = 'YOUR_PROJECT_ID';
  // const filter = 'metric.type="compute.googleapis.com/instance/cpu/utilization"';

  const request = {
    name: client.projectPath(projectId),
    filter: filter,
    interval: {
      startTime: {
        // Limit results to the last 20 minutes
        seconds: Date.now() / 1000 - 60 * 20,
      },
      endTime: {
        seconds: Date.now() / 1000,
      },
    },
  };

  // Writes time series data
  const [timeSeries] = await client.listTimeSeries(request);
  timeSeries.forEach(data => {
    console.log(`${data.metric.labels.instance_name}:`);
    data.points.forEach(point => {
      console.log(JSON.stringify(point.value));
    });
  });
}
readTimeSeriesData();

PHP

use Google\Cloud\Monitoring\V3\MetricServiceClient;
use Google\Cloud\Monitoring\V3\TimeInterval;
use Google\Cloud\Monitoring\V3\ListTimeSeriesRequest_TimeSeriesView;
use Google\Protobuf\Timestamp;

/**
 * Example:
 * ```
 * read_timeseries_simple($projectId);
 * ```
 *
 * @param string $projectId Your project ID
 */
function read_timeseries_simple($projectId, $minutesAgo = 20)
{
    $metrics = new MetricServiceClient([
        'projectId' => $projectId,
    ]);

    $projectName = $metrics->projectName($projectId);
    $filter = 'metric.type="compute.googleapis.com/instance/cpu/utilization"';

    // Limit results to the last 20 minutes
    $startTime = new Timestamp();
    $startTime->setSeconds(time() - (60 * $minutesAgo));
    $endTime = new Timestamp();
    $endTime->setSeconds(time());

    $interval = new TimeInterval();
    $interval->setStartTime($startTime);
    $interval->setEndTime($endTime);

    $view = ListTimeSeriesRequest_TimeSeriesView::FULL;

    $result = $metrics->listTimeSeries(
        $projectName,
        $filter,
        $interval,
        $view);

    printf('CPU utilization:' . PHP_EOL);
    foreach ($result->iterateAllElements() as $timeSeries) {
        $instanceName = $timeSeries->getMetric()->getLabels()['instance_name'];
        printf($instanceName . ':' . PHP_EOL);
        foreach ($timeSeries->getPoints() as $point) {
            printf('  ' . $point->getValue()->getDoubleValue() . PHP_EOL);
        }
    }
}

Python

from google.cloud import monitoring_v3

client = monitoring_v3.MetricServiceClient()
project_name = f"projects/{project_id}"
interval = monitoring_v3.TimeInterval()

now = time.time()
seconds = int(now)
nanos = int((now - seconds) * 10 ** 9)
interval = monitoring_v3.TimeInterval(
    {
        "end_time": {"seconds": seconds, "nanos": nanos},
        "start_time": {"seconds": (seconds - 1200), "nanos": nanos},
    }
)

results = client.list_time_series(
    request={
        "name": project_name,
        "filter": 'metric.type = "compute.googleapis.com/instance/cpu/utilization"',
        "interval": interval,
        "view": monitoring_v3.ListTimeSeriesRequest.TimeSeriesView.FULL,
    }
)
for result in results:
    print(result)

Ruby

# Your Google Cloud Platform project ID
# project_id = "YOUR_PROJECT_ID"

client = Google::Cloud::Monitoring.metric_service
project_name = client.project_path project: project_id

interval = Google::Cloud::Monitoring::V3::TimeInterval.new
now = Time.now
interval.end_time = Google::Protobuf::Timestamp.new seconds: now.to_i,
                                                    nanos:   now.nsec
interval.start_time = Google::Protobuf::Timestamp.new seconds: now.to_i - 1200,
                                                      nanos:   now.nsec
filter = 'metric.type = "compute.googleapis.com/instance/cpu/utilization"'
view = Google::Cloud::Monitoring::V3::ListTimeSeriesRequest::TimeSeriesView::FULL

results = client.list_time_series name:     project_name,
                                  filter:   filter,
                                  interval: interval,
                                  view:     view
results.each do |result|
  p result
end

The returned data includes 20 data points in each time series over the 20-minute period, because Compute Engine metrics are collected every minute. For more information, see Retention and latency of metric data. The API returns the data points in each time series in reverse time order; there is no override for this point ordering.

If you have difficulty, see Troubleshooting API calls.

Aggregating data

The timeSeries.list method can perform statistical aggregations and reductions on the returned time series data. The following sections demonstrate two examples; see the method's documentation for more options.

Example: Aligning time series

This example reduces the 20 individual utilization measurements in each time series to 2 measurements: the mean utilization for the two 10-minute periods within the 20-minute interval. The data from each time series is first aligned into 10-minute periods, and then the values in each 10-minute period are averaged.

This example turns the 20 measurements per time series into two per time series. This operation has two advantages: it smooths out the data, and it aligns the data from all time-series data on exact 10-minute boundaries. The data can then be processed further.

Protocol

Here are the sample parameters to timeSeries.list:

  • name: projects/PROJECT_ID
  • aggregation.alignmentPeriod: 600s
  • aggregation.perSeriesAligner: ALIGN_MEAN
  • filter: metric.type = "compute.googleapis.com/instance/cpu/utilization"
  • interval.startTime: 2021-09-01T00:00:00Z
  • interval.endTime: 2021-09-01T00:20:00Z
  • fields: timeSeries.metric,timeSeries.points

    To access the fields parameter, click Show standard parameters.

The filter for a single instance shown in the previous example is removed: this query returns much less data, so there is less need to restrict it to one VM instance.

Try It!

Before clicking the Execute button, change PROJECT_ID to the ID for your project, and adjust the end time to something recent and the start time to 20 minutes earlier.

The following sample result has a time series for each of three VM instances. Each time series has two data points, the mean utilization for the 10-minute alignment periods:

{
 "timeSeries": [
  {
   "metric": {
    "labels": {"instance_name": "your-first-instance"},
    "type": "compute.googleapis.com/instance/cpu/utilization"
   },
   "points": [
    {
     "interval": {
      "startTime": "2021-09-01T14:00:00.000Z",
      "endTime": "2021-09-01T14:00:00.000Z"
     },
     "value": { "doubleValue": 0.06688481346044381 }
    },
    {
     "interval": {
      "startTime": "2021-09-01T13:50:00.000Z",
      "endTime": "2021-09-01T13:50:00.000Z"
     },
     "value": {"doubleValue": 0.06786652821310177 }
    }
   ]
  },
  {
   "metric": {
    "labels": { "instance_name": "your-second-instance" },
    "type": "compute.googleapis.com/instance/cpu/utilization"
   },
   "points": [
    {
     "interval": {
      "startTime": "2021-09-01T14:00:00.000Z",
      "endTime": "2021-09-01T14:00:00.000Z"
     },
     "value": { "doubleValue": 0.04144239874207415 }
    },
    {
     "interval": {
      "startTime": "2021-09-01T13:50:00.000Z",
      "endTime": "2021-09-01T13:50:00.000Z"
     },
     "value": { "doubleValue": 0.04045793689050091 }
    }
   ]
  },
  {
   "metric": {
    "labels": { "instance_name": "your-third-instance" },
    "type": "compute.googleapis.com/instance/cpu/utilization"
   },
   "points": [
    {
     "interval": {
      "startTime": "2021-09-01T14:00:00.000Z",
      "endTime": "2021-09-01T14:00:00.000Z"
     },
     "value": { "doubleValue": 0.029650046587339607 }
    },
    {
     "interval": {
      "startTime": "2021-09-01T13:50:00.000Z",
      "endTime": "2021-09-01T13:50:00.000Z"
     },
     "value": { "doubleValue": 0.03053874224715402 }
    }
   ]
  }
 ]
}

To view the request as a cURL command, as an HTTP request, or in JavaScript, click Full screen in APIs Explorer.

C#

public static object ReadTimeSeriesAggregate(string projectId,
    string metricType = "compute.googleapis.com/instance/cpu/utilization")
{
    // Create client.
    MetricServiceClient metricServiceClient = MetricServiceClient.Create();
    // Initialize request argument(s).
    string filter = $"metric.type=\"{metricType}\"";
    ListTimeSeriesRequest request = new ListTimeSeriesRequest
    {
        ProjectName = new ProjectName(projectId),
        Filter = filter,
        Interval = new TimeInterval(),
    };
    // Create timestamp for current time formatted in seconds.
    long timeStamp = (long)(DateTime.UtcNow - s_unixEpoch).TotalSeconds;
    Timestamp startTimeStamp = new Timestamp();
    // Set startTime to limit results to the last 20 minutes.
    startTimeStamp.Seconds = timeStamp - (60 * 20);
    Timestamp endTimeStamp = new Timestamp();
    // Set endTime to current time.
    endTimeStamp.Seconds = timeStamp;
    TimeInterval interval = new TimeInterval();
    interval.StartTime = startTimeStamp;
    interval.EndTime = endTimeStamp;
    request.Interval = interval;
    // Aggregate results per matching instance
    Aggregation aggregation = new Aggregation();
    Duration alignmentPeriod = new Duration();
    alignmentPeriod.Seconds = 600;
    aggregation.AlignmentPeriod = alignmentPeriod;
    aggregation.PerSeriesAligner = Aggregation.Types.Aligner.AlignMean;
    // Add the aggregation to the request.
    request.Aggregation = aggregation;
    // Make the request.
    PagedEnumerable<ListTimeSeriesResponse, TimeSeries> response =
        metricServiceClient.ListTimeSeries(request);
    // Iterate over all response items, lazily performing RPCs as required.
    Console.WriteLine($"{projectId} CPU utilization:");
    foreach (var item in response)
    {
        var points = item.Points;
        var labels = item.Metric.Labels;
        Console.WriteLine($"{labels.Values.FirstOrDefault()}");
        if (points.Count > 0)
        {
            Console.WriteLine($"  Now: {points[0].Value.DoubleValue}");
        }
        if (points.Count > 1)
        {
            Console.WriteLine($"  10 min ago: {points[1].Value.DoubleValue}");
        }
    }
    return 0;
}

Go

import (
	"context"
	"fmt"
	"io"
	"time"

	monitoring "cloud.google.com/go/monitoring/apiv3"
	"github.com/golang/protobuf/ptypes/duration"
	"github.com/golang/protobuf/ptypes/timestamp"
	"google.golang.org/api/iterator"
	monitoringpb "google.golang.org/genproto/googleapis/monitoring/v3"
)

// readTimeSeriesAlign reads the last 20 minutes of the given metric and aligns
// everything on 10 minute intervals.
func readTimeSeriesAlign(w io.Writer, projectID string) error {
	ctx := context.Background()
	client, err := monitoring.NewMetricClient(ctx)
	if err != nil {
		return fmt.Errorf("NewMetricClient: %v", err)
	}
	defer client.Close()
	startTime := time.Now().UTC().Add(time.Minute * -20)
	endTime := time.Now().UTC()
	req := &monitoringpb.ListTimeSeriesRequest{
		Name:   "projects/" + projectID,
		Filter: `metric.type="compute.googleapis.com/instance/cpu/utilization"`,
		Interval: &monitoringpb.TimeInterval{
			StartTime: &timestamp.Timestamp{
				Seconds: startTime.Unix(),
			},
			EndTime: &timestamp.Timestamp{
				Seconds: endTime.Unix(),
			},
		},
		Aggregation: &monitoringpb.Aggregation{
			PerSeriesAligner: monitoringpb.Aggregation_ALIGN_MEAN,
			AlignmentPeriod: &duration.Duration{
				Seconds: 600,
			},
		},
	}
	it := client.ListTimeSeries(ctx, req)
	for {
		resp, err := it.Next()
		if err == iterator.Done {
			break
		}
		if err != nil {
			return fmt.Errorf("could not read time series value: %v", err)
		}
		fmt.Fprintln(w, resp.GetMetric().GetLabels()["instance_name"])
		fmt.Fprintf(w, "\tNow: %.4f\n", resp.GetPoints()[0].GetValue().GetDoubleValue())
		if len(resp.GetPoints()) > 1 {
			fmt.Fprintf(w, "\t10 minutes ago: %.4f\n", resp.GetPoints()[1].GetValue().GetDoubleValue())
		}
	}
	fmt.Fprintln(w, "Done")
	return nil
}

Java

MetricServiceClient metricServiceClient = MetricServiceClient.create();
String projectId = System.getProperty("projectId");
ProjectName name = ProjectName.of(projectId);

// Restrict time to last 20 minutes
long startMillis = System.currentTimeMillis() - ((60 * 20) * 1000);
TimeInterval interval =
    TimeInterval.newBuilder()
        .setStartTime(Timestamps.fromMillis(startMillis))
        .setEndTime(Timestamps.fromMillis(System.currentTimeMillis()))
        .build();

Aggregation aggregation =
    Aggregation.newBuilder()
        .setAlignmentPeriod(Duration.newBuilder().setSeconds(600).build())
        .setPerSeriesAligner(Aggregation.Aligner.ALIGN_MEAN)
        .build();

ListTimeSeriesRequest.Builder requestBuilder =
    ListTimeSeriesRequest.newBuilder()
        .setName(name.toString())
        .setFilter("metric.type=\"compute.googleapis.com/instance/cpu/utilization\"")
        .setInterval(interval)
        .setAggregation(aggregation);

ListTimeSeriesRequest request = requestBuilder.build();

ListTimeSeriesPagedResponse response = metricServiceClient.listTimeSeries(request);

System.out.println("Got timeseries: ");
for (TimeSeries ts : response.iterateAll()) {
  System.out.println(ts);
}

Node.js

// Imports the Google Cloud client library
const monitoring = require('@google-cloud/monitoring');

// Creates a client
const client = new monitoring.MetricServiceClient();

async function readTimeSeriesAggregate() {
  /**
   * TODO(developer): Uncomment and edit the following lines of code.
   */
  // const projectId = 'YOUR_PROJECT_ID';

  const request = {
    name: client.projectPath(projectId),
    filter: 'metric.type="compute.googleapis.com/instance/cpu/utilization"',
    interval: {
      startTime: {
        // Limit results to the last 20 minutes
        seconds: Date.now() / 1000 - 60 * 20,
      },
      endTime: {
        seconds: Date.now() / 1000,
      },
    },
    // Aggregate results per matching instance
    aggregation: {
      alignmentPeriod: {
        seconds: 600,
      },
      perSeriesAligner: 'ALIGN_MEAN',
    },
  };

  // Writes time series data
  const [timeSeries] = await client.listTimeSeries(request);
  console.log('CPU utilization:');
  timeSeries.forEach(data => {
    console.log(data.metric.labels.instance_name);
    console.log(`  Now: ${data.points[0].value.doubleValue}`);
    if (data.points.length > 1) {
      console.log(`  10 min ago: ${data.points[1].value.doubleValue}`);
    }
    console.log('=====');
  });
}
readTimeSeriesAggregate();

PHP

use Google\Cloud\Monitoring\V3\MetricServiceClient;
use Google\Cloud\Monitoring\V3\Aggregation_Aligner;
use Google\Cloud\Monitoring\V3\Aggregation;
use Google\Cloud\Monitoring\V3\TimeInterval;
use Google\Cloud\Monitoring\V3\ListTimeSeriesRequest_TimeSeriesView;
use Google\Protobuf\Duration;
use Google\Protobuf\Timestamp;

/**
 * Example:
 * ```
 * read_timeseries_align($projectId);
 * ```
 *
 * @param string $projectId Your project ID
 */
function read_timeseries_align($projectId, $minutesAgo = 20)
{
    $metrics = new MetricServiceClient([
        'projectId' => $projectId,
    ]);

    $projectName = $metrics->projectName($projectId);
    $filter = 'metric.type="compute.googleapis.com/instance/cpu/utilization"';

    $startTime = new Timestamp();
    $startTime->setSeconds(time() - (60 * $minutesAgo));
    $endTime = new Timestamp();
    $endTime->setSeconds(time());

    $interval = new TimeInterval();
    $interval->setStartTime($startTime);
    $interval->setEndTime($endTime);

    $alignmentPeriod = new Duration();
    $alignmentPeriod->setSeconds(600);
    $aggregation = new Aggregation();
    $aggregation->setAlignmentPeriod($alignmentPeriod);
    $aggregation->setPerSeriesAligner(Aggregation_Aligner::ALIGN_MEAN);

    $view = ListTimeSeriesRequest_TimeSeriesView::FULL;

    $result = $metrics->listTimeSeries(
        $projectName,
        $filter,
        $interval,
        $view,
        ['aggregation' => $aggregation]);

    printf('CPU utilization:' . PHP_EOL);
    foreach ($result->iterateAllElements() as $timeSeries) {
        printf($timeSeries->getMetric()->getLabels()['instance_name'] . PHP_EOL);
        printf('  Now: ');
        printf($timeSeries->getPoints()[0]->getValue()->getDoubleValue() . PHP_EOL);
        if (count($timeSeries->getPoints()) > 1) {
            printf('  10 minutes ago: ');
            printf($timeSeries->getPoints()[1]->getValue()->getDoubleValue() . PHP_EOL);
        }
    }
}

Python

from google.cloud import monitoring_v3

client = monitoring_v3.MetricServiceClient()
project_name = f"projects/{project_id}"

now = time.time()
seconds = int(now)
nanos = int((now - seconds) * 10 ** 9)
interval = monitoring_v3.TimeInterval(
    {
        "end_time": {"seconds": seconds, "nanos": nanos},
        "start_time": {"seconds": (seconds - 3600), "nanos": nanos},
    }
)
aggregation = monitoring_v3.Aggregation(
    {
        "alignment_period": {"seconds": 1200},  # 20 minutes
        "per_series_aligner": monitoring_v3.Aggregation.Aligner.ALIGN_MEAN,
    }
)

results = client.list_time_series(
    request={
        "name": project_name,
        "filter": 'metric.type = "compute.googleapis.com/instance/cpu/utilization"',
        "interval": interval,
        "view": monitoring_v3.ListTimeSeriesRequest.TimeSeriesView.FULL,
        "aggregation": aggregation,
    }
)
for result in results:
    print(result)

Ruby

# Your Google Cloud Platform project ID
# project_id = "YOUR_PROJECT_ID"

client = Google::Cloud::Monitoring.metric_service
project_name = client.project_path project: project_id

interval = Google::Cloud::Monitoring::V3::TimeInterval.new
now = Time.now
interval.end_time = Google::Protobuf::Timestamp.new seconds: now.to_i,
                                                    nanos:   now.nsec
interval.start_time = Google::Protobuf::Timestamp.new seconds: now.to_i - 1200,
                                                      nanos:   now.nsec
filter = 'metric.type = "compute.googleapis.com/instance/cpu/utilization"'
view = Google::Cloud::Monitoring::V3::ListTimeSeriesRequest::TimeSeriesView::FULL
aggregation = Google::Cloud::Monitoring::V3::Aggregation.new(
  alignment_period:   { seconds: 1200 },
  per_series_aligner: Google::Cloud::Monitoring::V3::Aggregation::Aligner::ALIGN_MEAN
)

results = client.list_time_series name:        project_name,
                                  filter:      filter,
                                  interval:    interval,
                                  view:        view,
                                  aggregation: aggregation
results.each do |result|
  p result
end

If you have difficulty, see Troubleshooting API calls.

Example: Reducing across time series

This example extends the previous example by combining the aligned time series from the three VM instances into a single time series that measures the average utilization of all instances.

Protocol

Following are the sample parameters to timeSeries.list, aggregation.crossSeriesReducer:

  • name: projects/PROJECT_ID
  • aggregation.alignmentPeriod: 600s
  • aggregation.crossSeriesReducer: REDUCE_MEAN
  • aggregation.perSeriesAligner: ALIGN_MEAN
  • filter: metric.type = "compute.googleapis.com/instance/cpu/utilization"
  • interval.start_time: 2021-09-01T00:00:00Z
  • interval.end_time: 2021-09-01T00:20:00Z
  • fields: timeSeries.metric,timeSeries.points

    To access the fields parameter, click Show standard parameters.

Try It!

Before clicking the Execute button, change PROJECT_ID to the ID for your project, and adjust the end time to something recent and the start time to 20 minutes earlier.

The following sample result has only one time series and two data points. Each point is the average of the utilization among the three VM instances during the time period:

{
 "timeSeries": [
  {
   "metric": {
    "type": "compute.googleapis.com/instance/cpu/utilization"
   },
   "points": [
    {
     "interval": {
      "startTime": "2021-09-01T14:00:00.000Z",
      "endTime": "2021-09-01T14:00:00.000Z"
     },
     "value": {
      "doubleValue": 0.045992419596619184
     }
    },
    {
     "interval": {
      "startTime": "2021-09-01T13:50:00.000Z",
      "endTime": "2021-09-01T13:50:00.000Z"
     },
     "value": {
      "doubleValue": 0.04628773578358556
     }
    }
   ]
  }
 ]
}

To view the request as a cURL command, as an HTTP request, or in JavaScript, click Full screen in APIs Explorer.

C#

public static object ReadTimeSeriesReduce(string projectId,
    string metricType = "compute.googleapis.com/instance/cpu/utilization")
{
    // Create client.
    MetricServiceClient metricServiceClient = MetricServiceClient.Create();
    // Initialize request argument(s).
    string filter = $"metric.type=\"{metricType}\"";
    ListTimeSeriesRequest request = new ListTimeSeriesRequest
    {
        ProjectName = new ProjectName(projectId),
        Filter = filter,
        Interval = new TimeInterval(),
    };
    // Create timestamp for current time formatted in seconds.
    long timeStamp = (long)(DateTime.UtcNow - s_unixEpoch).TotalSeconds;
    Timestamp startTimeStamp = new Timestamp();
    // Set startTime to limit results to the last 20 minutes.
    startTimeStamp.Seconds = timeStamp - (60 * 20);
    Timestamp endTimeStamp = new Timestamp();
    // Set endTime to current time.
    endTimeStamp.Seconds = timeStamp;
    TimeInterval interval = new TimeInterval();
    interval.StartTime = startTimeStamp;
    interval.EndTime = endTimeStamp;
    request.Interval = interval;
    // Aggregate results per matching instance.
    Aggregation aggregation = new Aggregation();
    Duration alignmentPeriod = new Duration();
    alignmentPeriod.Seconds = 600;
    aggregation.AlignmentPeriod = alignmentPeriod;
    aggregation.CrossSeriesReducer = Aggregation.Types.Reducer.ReduceMean;
    aggregation.PerSeriesAligner = Aggregation.Types.Aligner.AlignMean;
    // Add the aggregation to the request.
    request.Aggregation = aggregation;
    // Make the request.
    PagedEnumerable<ListTimeSeriesResponse, TimeSeries> response =
        metricServiceClient.ListTimeSeries(request);
    // Iterate over all response items, lazily performing RPCs as required.
    Console.WriteLine("CPU utilization:");
    foreach (var item in response)
    {
        var points = item.Points;
        Console.WriteLine("Average CPU utilization across all GCE instances:");
        Console.WriteLine($"  Last 10 min: {points[0].Value.DoubleValue}");
        Console.WriteLine($"  Last 10-20 min ago: {points[1].Value.DoubleValue}");
    }
    return 0;
}

Go

import (
	"context"
	"fmt"
	"io"
	"time"

	monitoring "cloud.google.com/go/monitoring/apiv3"
	"github.com/golang/protobuf/ptypes/duration"
	"github.com/golang/protobuf/ptypes/timestamp"
	"google.golang.org/api/iterator"
	monitoringpb "google.golang.org/genproto/googleapis/monitoring/v3"
)

// readTimeSeriesReduce reads the last 20 minutes of the given metric, aligns
// everything on 10 minute intervals, and combines values from different
// instances.
func readTimeSeriesReduce(w io.Writer, projectID string) error {
	ctx := context.Background()
	client, err := monitoring.NewMetricClient(ctx)
	if err != nil {
		return fmt.Errorf("NewMetricClient: %v", err)
	}
	defer client.Close()
	startTime := time.Now().UTC().Add(time.Minute * -20)
	endTime := time.Now().UTC()
	req := &monitoringpb.ListTimeSeriesRequest{
		Name:   "projects/" + projectID,
		Filter: `metric.type="compute.googleapis.com/instance/cpu/utilization"`,
		Interval: &monitoringpb.TimeInterval{
			StartTime: &timestamp.Timestamp{
				Seconds: startTime.Unix(),
			},
			EndTime: &timestamp.Timestamp{
				Seconds: endTime.Unix(),
			},
		},
		Aggregation: &monitoringpb.Aggregation{
			CrossSeriesReducer: monitoringpb.Aggregation_REDUCE_MEAN,
			PerSeriesAligner:   monitoringpb.Aggregation_ALIGN_MEAN,
			AlignmentPeriod: &duration.Duration{
				Seconds: 600,
			},
		},
	}
	it := client.ListTimeSeries(ctx, req)
	for {
		resp, err := it.Next()
		if err == iterator.Done {
			break
		}
		if err != nil {
			return fmt.Errorf("could not read time series value: %v", err)
		}
		fmt.Fprintln(w, "Average CPU utilization across all GCE instances:")
		fmt.Fprintf(w, "\tNow: %.4f\n", resp.GetPoints()[0].GetValue().GetDoubleValue())
		if len(resp.GetPoints()) > 1 {
			fmt.Fprintf(w, "\t10 minutes ago: %.4f\n", resp.GetPoints()[1].GetValue().GetDoubleValue())
		}
	}
	fmt.Fprintln(w, "Done")
	return nil
}

Java

MetricServiceClient metricServiceClient = MetricServiceClient.create();
String projectId = System.getProperty("projectId");
ProjectName name = ProjectName.of(projectId);

// Restrict time to last 20 minutes
long startMillis = System.currentTimeMillis() - ((60 * 20) * 1000);
TimeInterval interval =
    TimeInterval.newBuilder()
        .setStartTime(Timestamps.fromMillis(startMillis))
        .setEndTime(Timestamps.fromMillis(System.currentTimeMillis()))
        .build();

Aggregation aggregation =
    Aggregation.newBuilder()
        .setAlignmentPeriod(Duration.newBuilder().setSeconds(600).build())
        .setPerSeriesAligner(Aggregation.Aligner.ALIGN_MEAN)
        .setCrossSeriesReducer(Aggregation.Reducer.REDUCE_MEAN)
        .build();

ListTimeSeriesRequest.Builder requestBuilder =
    ListTimeSeriesRequest.newBuilder()
        .setName(name.toString())
        .setFilter("metric.type=\"compute.googleapis.com/instance/cpu/utilization\"")
        .setInterval(interval)
        .setAggregation(aggregation);

ListTimeSeriesRequest request = requestBuilder.build();

ListTimeSeriesPagedResponse response = metricServiceClient.listTimeSeries(request);

System.out.println("Got timeseries: ");
for (TimeSeries ts : response.iterateAll()) {
  System.out.println(ts);
}

Node.js

// Imports the Google Cloud client library
const monitoring = require('@google-cloud/monitoring');

// Creates a client
const client = new monitoring.MetricServiceClient();

async function readTimeSeriesReduce() {
  /**
   * TODO(developer): Uncomment and edit the following lines of code.
   */
  // const projectId = 'YOUR_PROJECT_ID';

  const request = {
    name: client.projectPath(projectId),
    filter: 'metric.type="compute.googleapis.com/instance/cpu/utilization"',
    interval: {
      startTime: {
        // Limit results to the last 20 minutes
        seconds: Date.now() / 1000 - 60 * 20,
      },
      endTime: {
        seconds: Date.now() / 1000,
      },
    },
    // Aggregate results per matching instance
    aggregation: {
      alignmentPeriod: {
        seconds: 600,
      },
      crossSeriesReducer: 'REDUCE_MEAN',
      perSeriesAligner: 'ALIGN_MEAN',
    },
  };

  // Writes time series data
  const [result] = await client.listTimeSeries(request);
  if (result.length === 0) {
    console.log('No data');
    return;
  }
  const reductions = result[0].points;

  console.log('Average CPU utilization across all GCE instances:');
  console.log(`  Last 10 min: ${reductions[0].value.doubleValue}`);
  console.log(`  10-20 min ago: ${reductions[0].value.doubleValue}`);
}
readTimeSeriesReduce();

PHP

use Google\Cloud\Monitoring\V3\MetricServiceClient;
use Google\Cloud\Monitoring\V3\Aggregation_Aligner;
use Google\Cloud\Monitoring\V3\Aggregation_Reducer;
use Google\Cloud\Monitoring\V3\Aggregation;
use Google\Cloud\Monitoring\V3\TimeInterval;
use Google\Cloud\Monitoring\V3\ListTimeSeriesRequest_TimeSeriesView;
use Google\Protobuf\Duration;
use Google\Protobuf\Timestamp;

/**
 * Example:
 * ```
 * read_timeseries_reduce($projectId);
 * ```
 *
 * @param string $projectId Your project ID
 */
function read_timeseries_reduce($projectId, $minutesAgo = 20)
{
    $metrics = new MetricServiceClient([
        'projectId' => $projectId,
    ]);

    $projectName = $metrics->projectName($projectId);
    $filter = 'metric.type="compute.googleapis.com/instance/cpu/utilization"';

    $startTime = new Timestamp();
    $startTime->setSeconds(time() - (60 * $minutesAgo));
    $endTime = new Timestamp();
    $endTime->setSeconds(time());

    $interval = new TimeInterval();
    $interval->setStartTime($startTime);
    $interval->setEndTime($endTime);

    $alignmentPeriod = new Duration();
    $alignmentPeriod->setSeconds(600);
    $aggregation = new Aggregation();
    $aggregation->setAlignmentPeriod($alignmentPeriod);
    $aggregation->setCrossSeriesReducer(Aggregation_Reducer::REDUCE_MEAN);
    $aggregation->setPerSeriesAligner(Aggregation_Aligner::ALIGN_MEAN);

    $view = ListTimeSeriesRequest_TimeSeriesView::FULL;

    $result = $metrics->listTimeSeries(
        $projectName,
        $filter,
        $interval,
        $view,
        ['aggregation' => $aggregation]);

    printf('Average CPU utilization across all GCE instances:' . PHP_EOL);
    if ($timeSeries = $result->iterateAllElements()->current()) {
        $reductions = $timeSeries->getPoints();
        printf('  Last 10 minutes: ');
        printf($reductions[0]->getValue()->getDoubleValue() . PHP_EOL);
        if (count($reductions) > 1) {
            printf('  10-20 minutes ago: ');
            printf($reductions[1]->getValue()->getDoubleValue() . PHP_EOL);
        }
    }
}

Python

from google.cloud import monitoring_v3

client = monitoring_v3.MetricServiceClient()
project_name = f"projects/{project_id}"

now = time.time()
seconds = int(now)
nanos = int((now - seconds) * 10 ** 9)
interval = monitoring_v3.TimeInterval(
    {
        "end_time": {"seconds": seconds, "nanos": nanos},
        "start_time": {"seconds": (seconds - 3600), "nanos": nanos},
    }
)
aggregation = monitoring_v3.Aggregation(
    {
        "alignment_period": {"seconds": 1200},  # 20 minutes
        "per_series_aligner": monitoring_v3.Aggregation.Aligner.ALIGN_MEAN,
        "cross_series_reducer": monitoring_v3.Aggregation.Reducer.REDUCE_MEAN,
        "group_by_fields": ["resource.zone"],
    }
)

results = client.list_time_series(
    request={
        "name": project_name,
        "filter": 'metric.type = "compute.googleapis.com/instance/cpu/utilization"',
        "interval": interval,
        "view": monitoring_v3.ListTimeSeriesRequest.TimeSeriesView.FULL,
        "aggregation": aggregation,
    }
)
for result in results:
    print(result)

Ruby

# Your Google Cloud Platform project ID
# project_id = "YOUR_PROJECT_ID"

client = Google::Cloud::Monitoring.metric_service
project_name = client.project_path project: project_id

interval = Google::Cloud::Monitoring::V3::TimeInterval.new
now = Time.now
interval.end_time = Google::Protobuf::Timestamp.new seconds: now.to_i,
                                                    nanos:   now.nsec
interval.start_time = Google::Protobuf::Timestamp.new seconds: now.to_i - 1200,
                                                      nanos:   now.nsec
filter = 'metric.type = "compute.googleapis.com/instance/cpu/utilization"'
view = Google::Cloud::Monitoring::V3::ListTimeSeriesRequest::TimeSeriesView::FULL
aggregation = Google::Cloud::Monitoring::V3::Aggregation.new(
  alignment_period:     { seconds: 1200 },
  per_series_aligner:   Google::Cloud::Monitoring::V3::Aggregation::Aligner::ALIGN_MEAN,
  cross_series_reducer: Google::Cloud::Monitoring::V3::Aggregation::Reducer::REDUCE_MEAN,
  group_by_fields:      ["resource.zone"]
)

results = client.list_time_series name:        project_name,
                                  filter:      filter,
                                  interval:    interval,
                                  view:        view,
                                  aggregation: aggregation
results.each do |result|
  p result
end

If you have difficulty, see Troubleshooting API calls.