Creating Custom Metrics

To define a custom metric, use the metricDescriptors.create API method to create a custom metric descriptor. While it is possible to simply write time series data for your metric and let Monitoring auto-create the metric descriptor, you should know what information goes into a metric definition. After creating your new custom metric descriptor, you can use the metric with the metric descriptor API methods and the time series API methods. You can also use the metric for charting and alerting in Monitoring.

Custom metric names

When you create a custom metric, you assign it a custom metric type name that is unique among the custom metrics in your GCP project. The type name must begin with custom.googleapis.com/, followed by either a simple name or a path name. Path names can help you to organize your custom metrics, but they are handled just like simple names. See Naming rules for more details. Here are examples of the two kinds of type names:

custom.googleapis.com/cpu_utilization
custom.googleapis.com/instance/cpu/utilization

Your custom metrics also have resource names that are unique among all GCP resources in all projects. The format of a resource name for a metric is:

projects/[PROJECT_ID]/metricDescriptors/[METRIC_TYPE]

If the previous custom metric examples were created in project my-project-id, then their resource names would be the following:

projects/my-project-id/metricDescriptors/custom.googleapis.com/cpu_utilization
projects/my-project-id/metricDescriptors/custom.googleapis.com/instance/cpu/utilization

Name or type? In the Monitoring API, metric type name fields are usually labeled type and resource name fields are usually labeled name. However, in conversation and some documentation, the type name is often called the "metric name."

Defining your custom metric

To create your custom metric, you must provide a MetricDescriptor object that specifies various information about the metric. Here is the information you'll need:

  • Choose a type name for the custom metric, as described in the previous section.

  • Choose a project in which to define your custom metric and write its time series data. Custom metrics for AWS should be created in the AWS connector project for your AWS account. The project you choose must also be a member of the Workspace where you monitor the metric. If you need the same metric in several projects, then make identical definitions of the metric in each project.

  • Choose a display name and description of the metric. The display name is used in Monitoring's user interface.

  • Choose the metric's kind, value type, and (optionally) units. Not all value types and metric kinds are supported for custom metrics. See Kinds of metrics.

  • Choose the metric's labels—their names, value types, and descriptions.

  • Choose which monitored resource objects you'll include with your metric's time series data points. You should think about this before creating your metric descriptor. The monitored resource type you use affects which metric labels you need. For example, if you include a VM instance object with your data, then you won't need a metric label to specify the instance. For more information, see Choosing a monitored resource type.

For more help in making these choices, you can browse the built-in metrics and look at their time series data.

Choosing a monitored resource type

Each of your metric's data points must include a monitored resource object. Points from different monitored resource objects are held in different time series.

You can use only the following monitored resource types in your custom metrics.

A common practice is to use the monitored resource objects that represent the physical resources where your application code is running. This has several advantages:

  • You get better performance compared with using a single resource type.
  • You avoid out-of-order data caused by multiple processes writing to the same time series.
  • Your custom metric data can be grouped with other metric data from the same resources.

If none of the instance-related resource types are appropriate, use global. For example, Google App Engine users should use global because the resource type gae_app is not permitted in custom metrics.

Call the create method

With your choices made, call the metricDescriptors.create method, passing in a MetricDescriptor object. Alternatively, see Auto-creation of custom metrics. After Monitoring creates the new metric descriptor, you cannot change the descriptor except by deleting and recreating it, in which case you lose all the time series data previously collected for the old metric descriptor.

It is usually an error to call metricDescriptors.create using the same type name as an existing custom metric descriptor. However, if all the fields of the new MetricDescriptor object match the fields of the existing descriptor exactly, then it is not an error but it has no effect.

Example

In the following example, you create a gauge custom metric, custom.googleapis.com/stores/daily_sales. The metric has a single dimension label, store_id.

Protocol

The following are the sample parameters to metricDescriptors.create:

  • name (URL): projects/[PROJECT_ID]
  • Request body: supply a MetricDescriptor object such as the following:

    {
      "name": "",
      "description": "Daily sales records from all branch stores.",
      "displayName": "daily sales",
      "type": "custom.googleapis.com/stores/daily_sales",
      "metricKind": "GAUGE",
      "valueType": "DOUBLE",
      "unit": "{USD}",
      "labels": [
        {
          "key": "store_id",
          "valueType": "STRING",
          "description": "The ID of the store."
        },
      ],
    }
    

When creating a new custom metric, the name field in the MetricDescriptor is ignored and can be omitted. The create method returns the new metric descriptor with the name field filled in, which in this example would be the following:

"name": "projects/[PROJECT_ID]/metricDescriptors/custom.googleapis.com/stores/daily_sales"

You use this name, for example, if you want to get a metric's descriptor.

Try It! (You might have to type ENTER in the request body field to see the contents.)

C#

        public static object CreateMetric(string projectId,
            string metricType = "custom.googleapis.com/stores/daily_sales")
        {
            // Create client.
            MetricServiceClient metricServiceClient = MetricServiceClient.Create();

            // Prepare custom metric descriptor.      
            MetricDescriptor metricDescriptor = new MetricDescriptor();
            metricDescriptor.DisplayName = "Daily Sales";
            metricDescriptor.Description = "Daily sales records from all branch stores.";
            metricDescriptor.MetricKind = MetricKind.Gauge;
            metricDescriptor.ValueType = MetricDescriptor.Types.ValueType.Double;
            metricDescriptor.Type = metricType;
            metricDescriptor.Unit = "{USD}";
            LabelDescriptor labels = new LabelDescriptor();
            labels.Key = "store_id";
            labels.ValueType = LabelDescriptor.Types.ValueType.String;
            labels.Description = "The ID of the store.";
            metricDescriptor.Labels.Add(labels);
            CreateMetricDescriptorRequest request = new CreateMetricDescriptorRequest
            {
                ProjectName = new ProjectName(projectId),
            };
            request.MetricDescriptor = metricDescriptor;
            // Make the request.
            MetricDescriptor response = metricServiceClient.CreateMetricDescriptor(request);
            Console.WriteLine("Done creating metric descriptor:");
            Console.WriteLine(JObject.Parse($"{response}").ToString());
            return 0;
        }

Go

// createCustomMetric creates a custom metric specified by the metric type.
func createCustomMetric(s *monitoring.Service, projectID, metricType string) error {
	ld := monitoring.LabelDescriptor{Key: "environment", ValueType: "STRING", Description: "An arbitrary measurement"}
	md := monitoring.MetricDescriptor{
		Type:        metricType,
		Labels:      []*monitoring.LabelDescriptor{&ld},
		MetricKind:  "GAUGE",
		ValueType:   "INT64",
		Unit:        "items",
		Description: "An arbitrary measurement",
		DisplayName: "Custom Metric",
	}
	resp, err := s.Projects.MetricDescriptors.Create(projectResource(projectID), &md).Do()
	if err != nil {
		return fmt.Errorf("Could not create custom metric: %v", err)
	}

	log.Printf("createCustomMetric: %s\n", formatResource(resp))
	return nil
}

Java

// Your Google Cloud Platform project ID
String projectId = System.getProperty("projectId");
String metricType = CUSTOM_METRIC_DOMAIN + "/" + type;

final MetricServiceClient client = MetricServiceClient.create();
ProjectName name = ProjectName.of(projectId);

MetricDescriptor descriptor = MetricDescriptor.newBuilder()
    .setType(metricType)
    .setDescription("This is a simple example of a custom metric.")
    .setMetricKind(MetricDescriptor.MetricKind.GAUGE)
    .setValueType(MetricDescriptor.ValueType.DOUBLE)
    .build();

CreateMetricDescriptorRequest request = CreateMetricDescriptorRequest.newBuilder()
    .setName(name.toString())
    .setMetricDescriptor(descriptor)
    .build();

client.createMetricDescriptor(request);

Node.js

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

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

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

const request = {
  name: client.projectPath(projectId),
  metricDescriptor: {
    description: 'Daily sales records from all branch stores.',
    displayName: 'Daily Sales',
    type: 'custom.googleapis.com/stores/daily_sales',
    metricKind: 'GAUGE',
    valueType: 'DOUBLE',
    unit: '{USD}',
    labels: [
      {
        key: 'store_id',
        valueType: 'STRING',
        description: 'The ID of the store.',
      },
    ],
  },
};

// Creates a custom metric descriptor
client
  .createMetricDescriptor(request)
  .then(results => {
    const descriptor = results[0];

    console.log('Created custom Metric:\n');
    console.log(`Name: ${descriptor.displayName}`);
    console.log(`Description: ${descriptor.description}`);
    console.log(`Type: ${descriptor.type}`);
    console.log(`Kind: ${descriptor.metricKind}`);
    console.log(`Value Type: ${descriptor.valueType}`);
    console.log(`Unit: ${descriptor.unit}`);
    console.log('Labels:');
    descriptor.labels.forEach(label => {
      console.log(
        `  ${label.key} (${label.valueType}) - ${label.description}`
      );
    });
  })
  .catch(err => {
    console.error('ERROR:', err);
  });

PHP

use Google\Cloud\Monitoring\V3\MetricServiceClient;
use Google\Api\LabelDescriptor;
use Google\Api\LabelDescriptor_ValueType;
use Google\Api\MetricDescriptor;
use Google\Api\MetricDescriptor_MetricKind;
use Google\Api\MetricDescriptor_ValueType;

/**
 * Create a new metric in Stackdriver Monitoring.
 * Example:
 * ```
 * create_metric($projectId);
 * ```
 *
 * @param string $projectId Your project ID
 */
function create_metric($projectId)
{
    $metrics = new MetricServiceClient([
        'projectId' => $projectId,
    ]);

    $projectName = $metrics->projectName($projectId);

    $descriptor = new MetricDescriptor();
    $descriptor->setDescription('Daily sales records from all branch stores.');
    $descriptor->setDisplayName('Daily Sales');
    $descriptor->setType('custom.googleapis.com/stores/daily_sales');
    $descriptor->setMetricKind(MetricDescriptor_MetricKind::GAUGE);
    $descriptor->setValueType(MetricDescriptor_ValueType::DOUBLE);
    $descriptor->setUnit('{USD}');
    $label = new LabelDescriptor();
    $label->setKey('store_id');
    $label->setValueType(LabelDescriptor_ValueType::STRING);
    $label->setDescription('The ID of the store.');
    $labels = [$label];
    $descriptor->setLabels($labels);

    $descriptor = $metrics->createMetricDescriptor($projectName, $descriptor);
    printf('Created a metric: ' . $descriptor->getName() . PHP_EOL);
}

Python

client = monitoring_v3.MetricServiceClient()
project_name = client.project_path(project_id)
descriptor = monitoring_v3.types.MetricDescriptor()
descriptor.type = 'custom.googleapis.com/my_metric'
descriptor.metric_kind = (
    monitoring_v3.enums.MetricDescriptor.MetricKind.GAUGE)
descriptor.value_type = (
    monitoring_v3.enums.MetricDescriptor.ValueType.DOUBLE)
descriptor.description = 'This is a simple example of a custom metric.'
descriptor = client.create_metric_descriptor(project_name, descriptor)
print('Created {}.'.format(descriptor.name))

See Troubleshooting API calls if you have difficulty.

Next step: See Writing metric data.

Deleting metrics

To delete a custom metric, call the metricDescriptors.delete method.

Protocol

You can only delete custom metric types. Here is an example of deleting your stores/daily_sales metric created in the previous section:

  • name: projects/[PROJECT_ID]/metricDescriptors/custom.googleapis.com/stores/daily_sales

Try It!

C#

public static object DeleteMetric(string projectId, string metricType)
{
    // Create client.
    MetricServiceClient metricServiceClient = MetricServiceClient.Create();
    // Initialize request argument(s).
    MetricDescriptorName name = new MetricDescriptorName(projectId, metricType);
    // Make the request.
    metricServiceClient.DeleteMetricDescriptor(name);
    Console.WriteLine($"Done deleting metric descriptor: {name}");
    return 0;
}

Java

String projectId = System.getProperty("projectId");
final MetricServiceClient client = MetricServiceClient.create();
MetricDescriptorName metricName = MetricDescriptorName.of(projectId, name);
client.deleteMetricDescriptor(metricName);
System.out.println("Deleted descriptor " + name);

Node.js

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

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

/**
 * TODO(developer): Uncomment and edit the following lines of code.
 */
// const projectId = 'YOUR_PROJECT_ID';
// const metricId = 'custom.googleapis.com/stores/daily_sales';

const request = {
  name: client.metricDescriptorPath(projectId, metricId),
};

// Deletes a metric descriptor
client
  .deleteMetricDescriptor(request)
  .then(results => {
    console.log(`Deleted ${metricId}`, results[0]);
  })
  .catch(err => {
    console.error('ERROR:', err);
  });

PHP

use Google\Cloud\Monitoring\V3\MetricServiceClient;

/**
 * Example:
 * ```
 * delete_metric($projectId, $databaseId);
 * ```
 *
 * @param string $projectId Your project ID
 * @param string $metricId  The ID of the Metric Descriptor to delete
 */
function delete_metric($projectId, $metricId)
{
    $metrics = new MetricServiceClient([
        'projectId' => $projectId,
    ]);

    $metricPath = $metrics->metricDescriptorName($projectId, $metricId);
    $ret = $metrics->deleteMetricDescriptor($metricPath);

    printf('Deleted a metric: ' . $metricPath . PHP_EOL);
}

Python

client = monitoring_v3.MetricServiceClient()
client.delete_metric_descriptor(descriptor_name)
print('Deleted metric descriptor {}.'.format(descriptor_name))

See Troubleshooting API calls if you have difficulty.

You cannot delete the time series data from your custom metric, but the data expires and is deleted according to the data retention policy.

Writing metric data

You can write data only to custom metric types. Use the timeSeries.create method to write the data points. The method appends a new data point to an existing time series, creating the time series if needed.

You write data points by passing a list of TimeSeries objects to timeSeries.create. Each object must specify a different time series, either in different metric types or in the same metric type:

  • Each time series is identified by the contents of the metric and resource fields of the TimeSeries object.
  • Omit the fields metricKind and valueType; they are ignored when writing data points.
  • Each TimeSeries object must contain only a single Point object:

    • The point's value and time interval must be consistent with the metric type's definition. For information on time intervals for different metric kinds, see Metric kinds.
    • The point's time interval must be later than any point already in the time series.
    • The end time of the interval must not be more than 24 hours in the past or more than five minutes in the future.
  • If you want to write more than one point to the same time series, then use a separate call to the timeSeries.create method for each point.

Best practice: When adding multiple data points to the same time series, do not add them faster than once per minute. If you are adding data points to different time series, then there is no rate limitation.

Protocol

To write a point to the stores/daily_sales custom metric used in the Creating metrics section, pass the following sample parameters to timeSeries.create method:

  • name: projects/[PROJECT_ID]
  • request body: include a list of TimeSeries objects. The following sample has only one time series in the list.

    {
     "timeSeries": [
      {
       "metric": {
        "type": "custom.googleapis.com/stores/daily_sales",
        "labels": {
         "store_id": "Pittsburgh"
        }
       },
       "resource": {
        "type": "global",
        "labels": {
         "project_id": "[PROJECT_ID]"
        }
       },
       "points": [
        {
         "interval": {
          "endTime": "2016-06-01T10:00:00-04:00"
         },
         "value": {
          "doubleValue": 123.45
         }
        }
       ]
      }
     ]
    }
    

Try It!

C#

        public static object WriteTimeSeriesData(string projectId)
        {
            // Create client.
            MetricServiceClient metricServiceClient = MetricServiceClient.Create();
            // Initialize request argument(s).
            ProjectName name = new ProjectName(projectId);
            // Prepare a data point. 
            Point dataPoint = new Point();
            TypedValue salesTotal = new TypedValue();
            salesTotal.DoubleValue = 123.45;
            dataPoint.Value = salesTotal;
            Timestamp timeStamp = new Timestamp();
            timeStamp.Seconds = (long)(DateTime.UtcNow - s_unixEpoch).TotalSeconds;
            TimeInterval interval = new TimeInterval();
            interval.EndTime = timeStamp;
            dataPoint.Interval = interval;

            // Prepare custom metric.
            Metric metric = new Metric();
            metric.Type = "custom.googleapis.com/stores/daily_sales";
            metric.Labels.Add("store_id", "Pittsburgh");

            // Prepare monitored resource.
            MonitoredResource resource = new MonitoredResource();
            resource.Type = "global";
            resource.Labels.Add("project_id", projectId);

            // Create a new time series using inputs.
            TimeSeries timeSeriesData = new TimeSeries();
            timeSeriesData.Metric = metric;
            timeSeriesData.Resource = resource;
            timeSeriesData.Points.Add(dataPoint);

            // Add newly created time series to list of time series to be written.
            IEnumerable<TimeSeries> timeSeries = new List<TimeSeries> { timeSeriesData };
            // Write time series data.
            metricServiceClient.CreateTimeSeries(name, timeSeries);
            Console.WriteLine("Done writing time series data:");
            Console.WriteLine(JObject.Parse($"{timeSeriesData}").ToString());
            return 0;
        }

Go

// writeTimeSeriesValue writes a value for the custom metric created
func writeTimeSeriesValue(s *monitoring.Service, projectID, metricType string) error {
	now := time.Now().UTC().Format(time.RFC3339Nano)
	randVal := rand.Int63n(10)
	timeseries := monitoring.TimeSeries{
		Metric: &monitoring.Metric{
			Type: metricType,
			Labels: map[string]string{
				"environment": "STAGING",
			},
		},
		Resource: &monitoring.MonitoredResource{
			Labels: map[string]string{
				"instance_id": "test-instance",
				"zone":        "us-central1-f",
			},
			Type: "gce_instance",
		},
		Points: []*monitoring.Point{
			{
				Interval: &monitoring.TimeInterval{
					StartTime: now,
					EndTime:   now,
				},
				Value: &monitoring.TypedValue{
					Int64Value: &randVal,
				},
			},
		},
	}

	createTimeseriesRequest := monitoring.CreateTimeSeriesRequest{
		TimeSeries: []*monitoring.TimeSeries{&timeseries},
	}

	log.Printf("writeTimeseriesRequest: %s\n", formatResource(createTimeseriesRequest))
	_, err := s.Projects.TimeSeries.Create(projectResource(projectID), &createTimeseriesRequest).Do()
	if err != nil {
		return fmt.Errorf("Could not write time series value, %v ", err)
	}
	return nil
}

Java

String projectId = System.getProperty("projectId");
// Instantiates a client
MetricServiceClient metricServiceClient = MetricServiceClient.create();

// Prepares an individual data point
TimeInterval interval = TimeInterval.newBuilder()
    .setEndTime(Timestamps.fromMillis(System.currentTimeMillis()))
    .build();
TypedValue value = TypedValue.newBuilder()
    .setDoubleValue(123.45)
    .build();
Point point = Point.newBuilder()
    .setInterval(interval)
    .setValue(value)
    .build();

List<Point> pointList = new ArrayList<>();
pointList.add(point);

ProjectName name = ProjectName.of(projectId);

// Prepares the metric descriptor
Map<String, String> metricLabels = new HashMap<>();
Metric metric = Metric.newBuilder()
    .setType("custom.googleapis.com/my_metric")
    .putAllLabels(metricLabels)
    .build();

// Prepares the monitored resource descriptor
Map<String, String> resourceLabels = new HashMap<>();
resourceLabels.put("instance_id", "1234567890123456789");
resourceLabels.put("zone", "us-central1-f");

MonitoredResource resource = MonitoredResource.newBuilder()
    .setType("gce_instance")
    .putAllLabels(resourceLabels)
    .build();

// Prepares the time series request
TimeSeries timeSeries = TimeSeries.newBuilder()
    .setMetric(metric)
    .setResource(resource)
    .addAllPoints(pointList)
    .build();

List<TimeSeries> timeSeriesList = new ArrayList<>();
timeSeriesList.add(timeSeries);

CreateTimeSeriesRequest request = CreateTimeSeriesRequest.newBuilder()
    .setName(name.toString())
    .addAllTimeSeries(timeSeriesList)
    .build();

// Writes time series data
metricServiceClient.createTimeSeries(request);
System.out.println("Done writing time series value.");

Node.js

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

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

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

const dataPoint = {
  interval: {
    endTime: {
      seconds: Date.now() / 1000,
    },
  },
  value: {
    doubleValue: 123.45,
  },
};

const timeSeriesData = {
  metric: {
    type: 'custom.googleapis.com/stores/daily_sales',
    labels: {
      store_id: 'Pittsburgh',
    },
  },
  resource: {
    type: 'global',
    labels: {
      project_id: projectId,
    },
  },
  points: [dataPoint],
};

const request = {
  name: client.projectPath(projectId),
  timeSeries: [timeSeriesData],
};

// Writes time series data
client
  .createTimeSeries(request)
  .then(results => {
    console.log(`Done writing time series data.`, results[0]);
  })
  .catch(err => {
    console.error('ERROR:', err);
  });

PHP

use Google\Api\Metric;
use Google\Api\MonitoredResource;
use Google\Cloud\Monitoring\V3\MetricServiceClient;
use Google\Cloud\Monitoring\V3\Point;
use Google\Cloud\Monitoring\V3\TimeInterval;
use Google\Cloud\Monitoring\V3\TimeSeries;
use Google\Cloud\Monitoring\V3\TypedValue;
use Google\Protobuf\Timestamp;

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

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

    $endTime = new Timestamp();
    $endTime->setSeconds(time());
    $interval = new TimeInterval();
    $interval->setEndTime($endTime);

    $value = new TypedValue();
    $value->setDoubleValue(123.45);

    $point = new Point();
    $point->setValue($value);
    $point->setInterval($interval);
    $points = [$point];

    $metric = new Metric();
    $metric->setType('custom.googleapis.com/stores/daily_sales');
    $labels = ['store_id' => 'Pittsburg'];
    $metric->setLabels($labels);

    $resource = new MonitoredResource();
    $resource->setType('global');
    $labels = ['project_id' => $projectId];
    $resource->setLabels($labels);

    $timeSeries = new TimeSeries();
    $timeSeries->setMetric($metric);
    $timeSeries->setResource($resource);
    $timeSeries->setPoints($points);

    $result = $metrics->createTimeSeries(
        $projectName,
        [$timeSeries]);

    printf('Done writing time series data.' . PHP_EOL);
}

Python

client = monitoring_v3.MetricServiceClient()
project_name = client.project_path(project_id)

series = monitoring_v3.types.TimeSeries()
series.metric.type = 'custom.googleapis.com/my_metric'
series.resource.type = 'gce_instance'
series.resource.labels['instance_id'] = '1234567890123456789'
series.resource.labels['zone'] = 'us-central1-f'
point = series.points.add()
point.value.double_value = 3.14
now = time.time()
point.interval.end_time.seconds = int(now)
point.interval.end_time.nanos = int(
    (now - point.interval.end_time.seconds) * 10**9)
client.create_time_series(project_name, [series])

See Troubleshooting API calls if you have difficulty.

Auto-creation of custom metrics

If you write metric data to a custom metric type that does not yet exist, then a new custom metric type is created for you automatically. Auto-creation is limited in the types of metrics it can create.

Specifically, during a call to timeSeries.create, if a TimeSeries object includes a Metric object for a nonexistent custom metric type, then Monitoring creates a new custom metric type whose MetricDescriptor has the following fields:

  • type: The type is copied from the Metric object's type field.
  • name: The name is created from the project ID in the method call and the custom metric type.
  • labels: The labels are those that appear in the Metric object. Each label descriptor in the new metric descriptor has the following fields:
    • key: the label key in the Metric object.
    • valueType: STRING
    • description: not set
  • metricKind: The default metric kind is GAUGE, but if you specify the metricKind parameter of the TimeSeries object, then the new metric has that kind. You can specify only GAUGE and CUMULATIVE kinds.
  • valueType: The value type is taken from the typed value of the Point being written. which must be BOOL, INT64, DOUBLE, or DISTRIBUTION. If you specify a value type in the valueType field of the TimeSeries, then that type must match the type of the Point.
  • unit: not set
  • description: "Auto created custom metric.".
  • displayName: not set

In a single timeSeries.create call you can include multiple TimeSeries objects that reference the same nonexistent custom metric type. In that case, the new type's fields are set in the same way, except that the labels in the new metric descriptor are the union of all the labels appearing in the Metric objects in the multiple time series.

After the custom metric type is created, you cannot change the new descriptor. For example, you cannot add or remove labels from the descriptor. You can delete the descriptor and start over.

Was this page helpful? Let us know how we did:

Send feedback about...

Stackdriver Monitoring