Skip to content

Commit

Permalink
Monitoring metric descriptor (#3754)
Browse files Browse the repository at this point in the history
* added metric descriptor resource and more functionality to PollAsync

* added handrwitten test for metric descriptor

* added a test case and cleaned up stale comments

* fixed small formatting things

* addressed more comments

Co-authored-by: Tiffany Shen <tishen@google.com>
  • Loading branch information
tishen25 and tiffunky authored Jul 22, 2020
1 parent cf5a68c commit f4c8be5
Show file tree
Hide file tree
Showing 16 changed files with 417 additions and 20 deletions.
2 changes: 1 addition & 1 deletion products/appengine/terraform.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ overrides: !ruby/object:Overrides::ResourceOverrides
import_format: ["apps/{{project}}/firewall/ingressRules/{{priority}}"]
mutex: "apps/{{project}}"
async: !ruby/object:Provider::Terraform::PollAsync
check_response_func: PollCheckForExistence
check_response_func_existence: PollCheckForExistence
actions: ['create']
operation: !ruby/object:Api::Async::Operation
timeouts: !ruby/object:Api::Timeouts
Expand Down
2 changes: 1 addition & 1 deletion products/bigquery/terraform.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -108,7 +108,7 @@ overrides: !ruby/object:Overrides::ResourceOverrides
import_format: ["projects/{{project}}/jobs/{{job_id}}"]
skip_delete: true
async: !ruby/object:Provider::Terraform::PollAsync
check_response_func: PollCheckForExistence
check_response_func_existence: PollCheckForExistence
actions: ['create']
operation: !ruby/object:Api::Async::Operation
timeouts: !ruby/object:Api::Timeouts
Expand Down
4 changes: 2 additions & 2 deletions products/cloudrun/terraform.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ overrides: !ruby/object:Overrides::ResourceOverrides
id_format: "locations/{{location}}/namespaces/{{project}}/domainmappings/{{name}}"
import_format: ["locations/{{location}}/namespaces/{{project}}/domainmappings/{{name}}"]
async: !ruby/object:Provider::Terraform::PollAsync
check_response_func: PollCheckKnativeStatus
check_response_func_existence: PollCheckKnativeStatus
actions: ['create', 'update']
operation: !ruby/object:Api::Async::Operation
timeouts: !ruby/object:Api::Timeouts
Expand Down Expand Up @@ -58,7 +58,7 @@ overrides: !ruby/object:Overrides::ResourceOverrides
id_format: "locations/{{location}}/namespaces/{{project}}/services/{{name}}"
import_format: ["locations/{{location}}/namespaces/{{project}}/services/{{name}}"]
async: !ruby/object:Provider::Terraform::PollAsync
check_response_func: PollCheckKnativeStatus
check_response_func_existence: PollCheckKnativeStatus
actions: ['create', 'update']
operation: !ruby/object:Api::Async::Operation
timeouts: !ruby/object:Api::Timeouts
Expand Down
2 changes: 1 addition & 1 deletion products/iap/terraform.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -152,7 +152,7 @@ overrides: !ruby/object:Overrides::ResourceOverrides
primary_resource_name: "fmt.Sprintf(\"tf-test-tunnel-vm%s\", context[\"random_suffix\"])"
Brand: !ruby/object:Overrides::Terraform::ResourceOverride
async: !ruby/object:Provider::Terraform::PollAsync
check_response_func: PollCheckForExistence
check_response_func_existence: PollCheckForExistence
actions: ['create']
operation: !ruby/object:Api::Async::Operation
timeouts: !ruby/object:Api::Timeouts
Expand Down
162 changes: 162 additions & 0 deletions products/monitoring/api.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -1829,3 +1829,165 @@ objects:
description: Values for all of the labels listed in the associated
monitored resource descriptor. For example, Compute Engine VM instances use
the labels "project_id", "instance_id", and "zone".

- !ruby/object:Api::Resource
name: MetricDescriptor
references: !ruby/object:Api::Resource::ReferenceLinks
guides:
'Official Documentation':
'https://cloud.google.com/monitoring/custom-metrics/'
api: 'https://cloud.google.com/monitoring/api/ref_v3/rest/v3/projects.metricDescriptors'
base_url: v3/projects/{{project}}/metricDescriptors
self_link: "v3/{{name}}"
update_verb: :POST
update_url: v3/projects/{{project}}/metricDescriptors
description: Defines a metric type and its schema. Once a metric descriptor is created,
deleting or altering it stops data collection and makes the metric type's existing data
unusable.
properties:
- !ruby/object:Api::Type::String
name: name
output: true
description: The resource name of the metric descriptor.
- !ruby/object:Api::Type::String
name: type
input: true
required: true
description: The metric type, including its DNS name prefix. The type is not
URL-encoded. All service defined metrics must be prefixed with the service name,
in the format of {service name}/{relative metric name}, such as
cloudsql.googleapis.com/database/cpu/utilization. The relative metric name must
have only upper and lower-case letters, digits, '/' and underscores '_' are
allowed. Additionally, the maximum number of characters allowed for the
relative_metric_name is 100. All user-defined metric types have the DNS name
custom.googleapis.com, external.googleapis.com, or logging.googleapis.com/user/.
- !ruby/object:Api::Type::Array
name: labels
description: The set of labels that can be used to describe a specific instance of this
metric type. In order to delete a label, the entire resource must be deleted,
then created with the desired labels.
item_type: !ruby/object:Api::Type::NestedObject
properties:
- !ruby/object:Api::Type::String
name: key
required: true
description: The key for this label. The key must not exceed 100 characters. The
first character of the key must be an upper- or lower-case letter, the remaining
characters must be letters, digits or underscores, and the key must match the
regular expression [a-zA-Z][a-zA-Z0-9_]*
- !ruby/object:Api::Type::Enum
name: valueType
description: The type of data that can be assigned to the label.
default_value: :STRING
values:
- :STRING
- :BOOL
- :INT64
- !ruby/object:Api::Type::String
name: description
description: A human-readable description for the label.
- !ruby/object:Api::Type::Enum
name: metricKind
input: true
required: true
description: Whether the metric records instantaneous values, changes to a value, etc.
Some combinations of metricKind and valueType might not be supported.
values:
- :METRIC_KIND_UNSPECIFIED
- :GAUGE
- :DELTA
- :CUMULATIVE
- !ruby/object:Api::Type::Enum
name: valueType
input: true
required: true
description: Whether the measurement is an integer, a floating-point number, etc. Some
combinations of metricKind and valueType might not be supported.
values:
- :BOOL
- :INT64
- :DOUBLE
- :STRING
- :DISTRIBUTION
- !ruby/object:Api::Type::String
name: unit
input: true
description: |
The units in which the metric value is reported. It is only applicable if the
valueType is INT64, DOUBLE, or DISTRIBUTION. The unit defines the representation of
the stored metric values.
Different systems may scale the values to be more easily displayed (so a value of
0.02KBy might be displayed as 20By, and a value of 3523KBy might be displayed as
3.5MBy). However, if the unit is KBy, then the value of the metric is always in
thousands of bytes, no matter how it may be displayed.

If you want a custom metric to record the exact number of CPU-seconds used by a job,
you can create an INT64 CUMULATIVE metric whose unit is s{CPU} (or equivalently
1s{CPU} or just s). If the job uses 12,005 CPU-seconds, then the value is written as
12005.

Alternatively, if you want a custom metric to record data in a more granular way, you
can create a DOUBLE CUMULATIVE metric whose unit is ks{CPU}, and then write the value
12.005 (which is 12005/1000), or use Kis{CPU} and write 11.723 (which is 12005/1024).
The supported units are a subset of The Unified Code for Units of Measure standard.
More info can be found in the API documentation
(https://cloud.google.com/monitoring/api/ref_v3/rest/v3/projects.metricDescriptors).
- !ruby/object:Api::Type::String
name: description
input: true
required: true
description: A detailed description of the metric, which can be used in documentation.
- !ruby/object:Api::Type::String
name: displayName
input: true
required: true
description: A concise name for the metric, which can be displayed in user interfaces.
Use sentence case without an ending period, for example "Request count".
- !ruby/object:Api::Type::NestedObject
name: metadata
input: true
description: Metadata which can be used to guide usage of the metric.
properties:
- !ruby/object:Api::Type::String
name: samplePeriod
at_least_one_of:
- metadata.0.sample_period
- metadata.0.ingest_delay
description: The sampling period of metric data points. For metrics which are
written periodically, consecutive data points are stored at this time interval,
excluding data loss due to errors. Metrics with a higher granularity have a
smaller sampling period. In
`[duration format](https://developers.google.com/protocol-buffers/docs/reference/google.protobuf?&_ga=2.264881487.1507873253.1593446723-935052455.1591817775#google.protobuf.Duration)`.
- !ruby/object:Api::Type::String
name: ingestDelay
at_least_one_of:
- metadata.0.sample_period
- metadata.0.ingest_delay
description: The delay of data points caused by ingestion. Data points older than
this age are guaranteed to be ingested and available to be read, excluding data
loss due to errors. In
`[duration format](https://developers.google.com/protocol-buffers/docs/reference/google.protobuf?&_ga=2.264881487.1507873253.1593446723-935052455.1591817775#google.protobuf.Duration)`.
- !ruby/object:Api::Type::Enum
name: launchStage
input: true
description: The launch stage of the metric definition.
values:
- :LAUNCH_STAGE_UNSPECIFIED
- :UNIMPLEMENTED
- :PRELAUNCH
- :EARLY_ACCESS
- :ALPHA
- :BETA
- :GA
- :DEPRECATED
- !ruby/object:Api::Type::Array
name: monitoredResourceTypes
output: true
description: If present, then a time series, which is identified partially by
a metric type and a MonitoredResourceDescriptor, that is associated with this metric
type can only be associated with one of the monitored resource types listed here.
This field allows time series to be associated with the intersection of this metric
type and the monitored resource types in this list.
item_type: Api::Type::String

4 changes: 3 additions & 1 deletion products/monitoring/inspec.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -35,4 +35,6 @@ overrides: !ruby/object:Overrides::ResourceOverrides
Slo: !ruby/object:Overrides::Inspec::ResourceOverride
exclude: true
UptimeCheckConfig: !ruby/object:Overrides::Inspec::ResourceOverride
exclude: true
exclude: true
MetricDescriptor: !ruby/object:Overrides::Inspec::ResourceOverride
exclude: true
34 changes: 34 additions & 0 deletions products/monitoring/terraform.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -277,6 +277,40 @@ overrides: !ruby/object:Overrides::ResourceOverrides
custom_expand: "templates/terraform/custom_expand/resource_from_self_link.go.erb"
custom_flatten: "templates/terraform/custom_flatten/group_id_to_name.erb"

MetricDescriptor: !ruby/object:Overrides::Terraform::ResourceOverride
async: !ruby/object:Provider::Terraform::PollAsync
check_response_func_existence: PollCheckForExistence
check_response_func_absence: PollCheckForAbsence
target_occurrences: 20
actions: ['create', 'update', 'delete']
operation: !ruby/object:Api::Async::Operation
timeouts: !ruby/object:Api::Timeouts
insert_minutes: 6
update_minutes: 6
delete_minutes: 6
id_format: "{{name}}"
import_format: ["{{name}}"]
error_retry_predicates: ["isMonitoringConcurrentEditError"]
properties:
labels: !ruby/object:Overrides::Terraform::PropertyOverride
is_set: true
labels.valueType: !ruby/object:Overrides::Terraform::PropertyOverride
custom_flatten: "templates/terraform/custom_flatten/default_if_empty.erb"
metadata: !ruby/object:Overrides::Terraform::PropertyOverride
ignore_read: true
launchStage: !ruby/object:Overrides::Terraform::PropertyOverride
ignore_read: true
examples:
- !ruby/object:Provider::Terraform::Examples
name: "monitoring_metric_descriptor_basic"
primary_resource_id: "basic"
- !ruby/object:Provider::Terraform::Examples
name: "monitoring_metric_descriptor_alert"
primary_resource_id: "with_alert"
custom_code: !ruby/object:Provider::Terraform::CustomCode
custom_import: templates/terraform/custom_import/self_link_as_name.erb


files: !ruby/object:Provider::Config::Files
# These files have templating (ERB) code that will be run.
# This is usually to add licensing info, autogeneration notices, etc.
Expand Down
4 changes: 2 additions & 2 deletions products/pubsub/terraform.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ overrides: !ruby/object:Overrides::ResourceOverrides
# resource until it exists and the negative cached result goes away.
# Context: terraform-providers/terraform-provider-google#4993
async: !ruby/object:Provider::Terraform::PollAsync
check_response_func: PollCheckForExistence
check_response_func_existence: PollCheckForExistence
actions: ['create']
operation: !ruby/object:Api::Async::Operation
timeouts: !ruby/object:Api::Timeouts
Expand Down Expand Up @@ -71,7 +71,7 @@ overrides: !ruby/object:Overrides::ResourceOverrides
# resource until it exists and the negative cached result goes away.
# Context: terraform-providers/terraform-provider-google#4993
async: !ruby/object:Provider::Terraform::PollAsync
check_response_func: PollCheckForExistence
check_response_func_existence: PollCheckForExistence
actions: ['create']
operation: !ruby/object:Api::Async::Operation
timeouts: !ruby/object:Api::Timeouts
Expand Down
17 changes: 14 additions & 3 deletions provider/terraform/async.rb
Original file line number Diff line number Diff line change
Expand Up @@ -20,8 +20,13 @@ class Terraform < Provider::AbstractCore
class PollAsync < Api::Async
# Details how to poll for an eventually-consistent resource state.

# Function to call for checking the Poll response
attr_reader :check_response_func
# Function to call for checking the Poll response for
# creating and updating a resource
attr_reader :check_response_func_existence

# Function to call for checking the Poll response for
# deleting a resource
attr_reader :check_response_func_absence

# Custom code to get a poll response, if needed.
# Will default to same logic as Read() to get current resource
Expand All @@ -31,12 +36,18 @@ class PollAsync < Api::Async
# result of the final Read()
attr_reader :suppress_error

# Number of times the desired state has to occur continuously
# during polling before returning a success
attr_reader :target_occurrences

def validate
super

check :check_response_func, type: String, required: true
check :check_response_func_existence, type: String, required: true
check :check_response_func_absence, type: String, default: 'PollCheckForAbsence'
check :custom_poll_read, type: String
check :suppress_error, type: :boolean, default: false
check :target_occurrences, type: Integer, default: 1
end
end
end
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,7 @@
}

// PerInstanceConfig goes into "DELETING" state while the instance is actually deleted
err = PollingWaitTime(resourceComputePerInstanceConfigPollRead(d, meta), PollCheckInstanceConfigDeleted, "Deleting PerInstanceConfig", d.Timeout(schema.TimeoutDelete))
err = PollingWaitTime(resourceComputePerInstanceConfigPollRead(d, meta), PollCheckInstanceConfigDeleted, "Deleting PerInstanceConfig", d.Timeout(schema.TimeoutDelete), 1)
if err != nil {
return fmt.Errorf("Error waiting for delete on PerInstanceConfig %q: %s", d.Id(), err)
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,7 @@
}

// RegionPerInstanceConfig goes into "DELETING" state while the instance is actually deleted
err = PollingWaitTime(resourceComputeRegionPerInstanceConfigPollRead(d, meta), PollCheckInstanceConfigDeleted, "Deleting RegionPerInstanceConfig", d.Timeout(schema.TimeoutDelete))
err = PollingWaitTime(resourceComputeRegionPerInstanceConfigPollRead(d, meta), PollCheckInstanceConfigDeleted, "Deleting RegionPerInstanceConfig", d.Timeout(schema.TimeoutDelete), 1)
if err != nil {
return fmt.Errorf("Error waiting for delete on RegionPerInstanceConfig %q: %s", d.Id(), err)
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
resource "google_monitoring_metric_descriptor" "<%= ctx[:primary_resource_id] %>" {
description = "Daily sales records from all branch stores."
display_name = "Daily sales"
type = "custom.googleapis.com/stores/daily_sales"
metric_kind = "GAUGE"
value_type = "DOUBLE"
unit = "{USD}"
}

resource "google_monitoring_alert_policy" "alert_policy" {
display_name = "Alert on daily sales"
combiner = "OR"
conditions {
display_name = "test condition"
condition_threshold {
filter = "metric.type=\"${google_monitoring_metric_descriptor.<%= ctx[:primary_resource_id] %>.type}\" AND resource.type=\"gce_instance\""
duration = "60s"
comparison = "COMPARISON_GT"
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
resource "google_monitoring_metric_descriptor" "<%= ctx[:primary_resource_id] %>" {
description = "Daily sales records from all branch stores."
display_name = "Daily sales"
type = "custom.googleapis.com/stores/daily_sales"
metric_kind = "GAUGE"
value_type = "DOUBLE"
unit = "{USD}"
labels {
key = "store_id"
value_type = "STRING"
description = "The ID of the store."
}
launch_stage = "BETA"
metadata {
sample_period = "60s"
ingest_delay = "30s"
}
}
Loading

0 comments on commit f4c8be5

Please sign in to comment.