Monitoring and Observability
|
This content was generated with the assistance of AI and should be verified against the official documentation before being relied on in production. See the section bibliography for the reference material consulted while preparing these pages. |
Commands and limits below are current for the gcloud CLI 586.x line (gcloud logging and gcloud monitoring
command groups, with gcloud beta monitoring channels for notification channels), the Google Cloud Observability
documentation and release notes published through 2026-09-29, Spring Boot 3.4 or later (structured logging and
Micrometer Tracing), the Google Cloud Client Libraries libraries-bom and Terraform hashicorp/google v8 (checked
2026-09-30). Product naming has moved several times (Stackdriver, then Operations Suite, now Google Cloud
Observability), and parts of the Log Analytics user interface are labelled differently from one release to the next,
so re-verify names against the console and the linked reference pages before relying on them in a pipeline.
Observability is the ability to answer "what is my system doing and why?" from the signals it emits. Google Cloud groups its tools under Google Cloud Observability: Cloud Logging (events), Cloud Monitoring (metrics, dashboards, alerts, uptime checks, SLOs), Cloud Trace (request latency across services), Cloud Profiler (where CPU and memory are spent), and Error Reporting (grouped exceptions). Most Google Cloud services emit logs and system metrics with no setup at all; your job is to add application signals, route and retain them sensibly, and attach alerts to the symptoms users feel.
In the Bookshelf scenario (see Google Cloud) catalog-api and orders-api run on Cloud Run
(Cloud Run), notifier consumes the orders topic, and the same services also exist as
Pods in the bookshelf-gke cluster (Deploying Microservices on GKE). This page wires them for
logs, metrics, traces, profiles and errors, sends audit logs to a long-retention bucket, alerts when catalog-api
returns server errors, and checks that the public front end answers.
Prerequisites
PROJECT_ID=$(gcloud config get-value project)
PROJECT_NUMBER=$(gcloud projects describe "$PROJECT_ID" --format='value(projectNumber)')
REGION=us-central1
gcloud services enable \
logging.googleapis.com \
monitoring.googleapis.com \
cloudtrace.googleapis.com \
cloudprofiler.googleapis.com \
clouderrorreporting.googleapis.com \
telemetry.googleapis.com
Derived from Enable and disable services.
In the console, select the project in the project picker at the top of the page and open Observability (or Logging, Monitoring, Trace, Profiler, Error Reporting from the navigation menu). Cloud Logging and Cloud Monitoring are enabled by default in every project; the Trace, Profiler, Error Reporting and Telemetry APIs are the ones you usually enable yourself. Cloud Shell has the gcloud CLI preinstalled and authenticated as your user.
The roles you meet most often are summarised below. Grant them to the service account a workload runs as (never to downloaded keys; see Identity and Access).
| Role | Allows |
|---|---|
|
Write log entries. Cloud Run and GKE node service accounts normally already have it. |
|
Read logs; the second also reads Data Access audit logs. |
|
Create buckets, sinks, exclusions and log-based metrics. |
|
Write custom and Prometheus metrics. |
|
Read dashboards and metrics; create alerting policies, channels and uptime checks. |
|
Write spans (needed by an application exporting traces). |
|
Upload profiles from the profiling agent. |
|
Send error events to Error Reporting. |
Derived from Logging access control, Monitoring access control and Understanding roles.
Cloud Logging
Cloud Logging collects log entries, stores them in log buckets, and lets you search, analyse, route and alert on
them. Each entry has a resource (for example cloud_run_revision or k8s_container), a severity, a timestamp, and a
payload that is text or structured JSON. Google Cloud services write logs on your behalf; for your own code on Cloud
Run, GKE, App Engine and Cloud Run functions, anything written to standard output or standard error is collected
automatically, with no agent to install.
Writing useful application logs
Plain text lines become one entry each, with severity DEFAULT. A single-line JSON object is parsed into a
structured payload, and a few well-known fields are promoted: severity, message, logging.googleapis.com/trace
(links the log to a Cloud Trace span) and logging.googleapis.com/spanId. Since Spring Boot 3.4 the built-in
structured logging can emit exactly that shape:
# application.properties of catalog-api
logging.structured.format.console=gcp
logging.level.com.example.bookshelf=INFO
Derived from Spring Boot structured logging and Structured logging.
Logger configuration, MDC fields and per-environment log levels are covered in Logging: Logback Defaults, Structured Output, and Container-Friendly Routing;
container stdout conventions are in Resources, Logging and Monitoring. For custom code
that has to write entries directly, the Java client library (google-cloud-logging) or the Spring Cloud GCP
spring-cloud-gcp-starter-logging starter exist, but stdout is simpler and cheaper to operate.
Log buckets and retention
Every project has two buckets that you cannot delete: _Required (audit logs such as Admin Activity, retained 400
days, free, not editable) and _Default (everything else, retained 30 days by default). Two sinks, also named
_Required and _Default, route entries into them. You can add user-defined buckets with their own region,
retention (1 day to 3650 days), CMEK key and access control, and you can lock a bucket’s retention so that it cannot
be shortened.
| Concept | Meaning |
|---|---|
Log bucket |
Storage container for entries in one location ( |
Log view |
A filtered window onto a bucket (for example only one team’s logs) that IAM can be granted on. |
Sink |
A routing rule: an inclusion filter plus a destination (a log bucket, BigQuery dataset, Cloud Storage bucket, Pub/Sub topic or another project’s bucket). Sinks copy; they do not move. |
Exclusion |
A filter that drops matching entries at ingestion so they are neither stored nor billed. Exclusions cannot be
applied to |
Log-based metric |
A counter or distribution computed from matching entries, usable in dashboards and alerts. |
Derived from Routing and storage overview and Configure log buckets.
In the Google Cloud console (Logs Explorer)
-
Open Logging → Logs Explorer.
-
Pick the time range, then use the Resource type and Severity drop-downs or type a query such as
resource.type="cloud_run_revision" AND resource.labels.service_name="catalog-api" AND severity>=ERROR. -
Click Run query. Expand an entry to see the payload; use Show similar entries or click a field to add it to the query.
-
Use Create alert to turn the query into a log-based alert, or More actions → Create sink / Create metric to route or count the matches.
-
Open Logging → Log Storage to see buckets, retention and size, to create a bucket, and to upgrade it to Log Analytics. Open Logging → Log Router to manage sinks and exclusions.
With the gcloud CLI
# Last 20 errors of catalog-api, newest first
gcloud logging read \
'resource.type="cloud_run_revision" AND resource.labels.service_name="catalog-api" AND severity>=ERROR' \
--project="$PROJECT_ID" --limit=20 --freshness=1d \
--format='table(timestamp, severity, textPayload, jsonPayload.message)'
# Write a test entry, then follow the stream
gcloud logging write bookshelf-demo '{"message":"hello from the CLI","orderId":"demo-1"}' \
--payload-type=json --severity=NOTICE
gcloud beta logging tail 'logName="projects/'"$PROJECT_ID"'/logs/bookshelf-demo"'
# Buckets and retention
gcloud logging buckets list --location=global
gcloud logging buckets update _Default --location=global --retention-days=60
gcloud logging buckets create bookshelf-audit \
--location=global --retention-days=400 --enable-analytics \
--description="Long-retention audit logs"
Derived from Using the gcloud CLI with Logging, gcloud logging read and gcloud logging buckets create.
Querying uses the Logging query language: field=value, comparison operators (>= works on severity), AND/OR/NOT,
: for "contains" and =~ for regular expressions. Always include a timestamp bound or --freshness so that the
query scans a small slice, because both speed and the quota on reads depend on it.
Sinks: routing and archiving
A sink needs a writer identity, a service account that Logging creates for it, and that identity needs write
permission on the destination. The following archives the audit logs of the project into the bookshelf-audit bucket
and exports ERROR entries to BigQuery for analysis.
# 1. Sink audit logs to the dedicated log bucket
gcloud logging sinks create audit-to-bucket \
"logging.googleapis.com/projects/$PROJECT_ID/locations/global/buckets/bookshelf-audit" \
--log-filter='logName:"cloudaudit.googleapis.com"'
# 2. Sink errors to a BigQuery dataset (partitioned tables)
bq --location=US mk --dataset "$PROJECT_ID:bookshelf_errors"
gcloud logging sinks create errors-to-bq \
"bigquery.googleapis.com/projects/$PROJECT_ID/datasets/bookshelf_errors" \
--log-filter='severity>=ERROR AND resource.type="cloud_run_revision"' \
--use-partitioned-tables
# 3. Allow the sink's writer identity to write to the dataset
WRITER=$(gcloud logging sinks describe errors-to-bq --format='value(writerIdentity)')
bq add-iam-policy-binding --member="$WRITER" --role=roles/bigquery.dataEditor \
"$PROJECT_ID:bookshelf_errors"
gcloud logging sinks list
Derived from Configure and manage sinks, Route logs to BigQuery and gcloud logging sinks create.
Sinks to a log bucket in the same project need no extra grant. For Cloud Storage use roles/storage.objectCreator,
and for Pub/Sub use roles/pubsub.publisher, on the destination. For a whole organisation or folder, create an
aggregated sink with --organization=ORG_ID or --folder=FOLDER_ID and --include-children, which is the
standard way to centralise audit logs in a security project. Sinks only act on entries received after they are
created, so nothing can be back-filled; plan the routing before the data you need arrives.
Exclusions reduce cost by dropping noisy entries before storage:
# Drop health-check noise from the _Default bucket
gcloud logging sinks update _Default \
--add-exclusion='name=drop-health-checks,filter=resource.type="cloud_run_revision" AND httpRequest.requestUrl:"/actuator/health" AND severity<WARNING'
Derived from Exclusion filters.
Log Analytics (SQL over logs)
Upgrading a log bucket to Log Analytics (--enable-analytics) lets you query it with SQL in the console, using
BigQuery’s query engine, without exporting anything. A linked BigQuery dataset additionally exposes the bucket to
BigQuery itself, so existing dashboards and joins with business data keep working. Depending on the console release
the page is labelled Log Analytics or Observability Analytics; the feature is the same.
gcloud logging links create bookshelf_audit_link \
--bucket=bookshelf-audit --location=global \
--description="BigQuery view of the audit bucket"
Derived from Log Analytics and Create a linked BigQuery dataset.
A query counts which principals changed IAM policies this week (open Logging → Log Analytics, choose the bucket’s
_AllLogs view):
SELECT
proto_payload.audit_log.authentication_info.principal_email AS principal,
COUNT(*) AS changes
FROM `my-project-id.global.bookshelf-audit._AllLogs`
WHERE timestamp > TIMESTAMP_SUB(CURRENT_TIMESTAMP(), INTERVAL 7 DAY)
AND proto_payload.audit_log.method_name = 'SetIamPolicy'
GROUP BY principal
ORDER BY changes DESC
LIMIT 20
Derived from Sample SQL queries for Log Analytics.
Log-based metrics
A log-based metric turns log entries into a time series that Cloud Monitoring can chart and alert on. A counter metric counts matching entries, a distribution metric extracts a numeric field (for example a latency) into buckets. System-defined log-based metrics exist for platform events; user-defined ones are billed by the data they ingest as for any custom metric.
gcloud logging metrics create orders_failed \
--description="Failed order submissions in orders-api" \
--log-filter='resource.type="cloud_run_revision" AND resource.labels.service_name="orders-api" AND jsonPayload.event="order_failed"'
gcloud logging metrics list
Derived from Log-based metrics and gcloud logging metrics create.
The metric appears in Monitoring as logging.googleapis.com/user/orders_failed. Metrics only count entries that
arrive after they are created. Prefer an application metric (see Micrometer below) when you control the code; use
log-based metrics for third-party components and for platform logs you cannot change.
Audit logs
Cloud Audit Logs answer "who did what, where and when" and are written for you:
| Log | Content |
|---|---|
Admin Activity |
API calls that change configuration or metadata (create a bucket, set an IAM policy). Always on, free, cannot be
disabled, retained 400 days in |
Data Access |
Reads of configuration and of user data (list objects, read a secret). Disabled by default except for BigQuery, billed as ordinary logs when enabled, and enabled per service and per log type. |
System Event |
Google-initiated administrative actions such as live migration. Always on. |
Policy Denied |
Requests denied by a VPC Service Controls or organisation policy. On by default. |
Enable Data Access logs selectively (for Secret Manager and Cloud KMS they are worth the cost) in IAM & Admin → Audit
Logs, or by editing the IAM policy’s auditConfigs. The full security-side treatment, including organisation-wide
sinks and the policy that forbids disabling them, is in Governance, Security and Compliance.
Derived from Cloud Audit Logs overview and Configure Data Access audit logs.
Cloud Monitoring
Cloud Monitoring stores time series. Almost every Google Cloud service publishes system metrics automatically and
free of charge (for example run.googleapis.com/request_count, compute.googleapis.com/instance/cpu/utilization,
cloudsql.googleapis.com/database/cpu/utilization). You add custom metrics (custom.googleapis.com/…),
external metrics and Prometheus metrics (prometheus.googleapis.com/…) for what the platform cannot know.
A metrics scope collects metrics of one or more projects so that a single scoping project can show them
together, which is the usual setup for a team that owns several projects.
Metrics are queried with the Metrics Explorer builder, with PromQL (recommended and natively supported), or with the older Monitoring Query Language (MQL), which has been deprecated in favour of PromQL for new alerting policies; check the MQL page before building anything new on it.
Dashboards
In the Google Cloud console
-
Open Monitoring → Dashboards. Google provides ready-made Cloud Run, GKE, Cloud SQL and VM Instances dashboards in the Dashboard Library; click Import to copy one into your project.
-
To build your own, click Create custom dashboard, then Add widget and choose a chart, gauge, scorecard or text.
-
In the widget, pick a metric (for example Cloud Run Revision → Request count), group by
response_code_class, and set the alignment period. -
Save the dashboard and share its link or grant
roles/monitoring.viewer.
With the gcloud CLI
Dashboards are JSON documents and are managed with the gcloud monitoring dashboards group:
cat > catalog-dashboard.json <<'JSON'
{
"displayName": "Bookshelf catalog-api",
"mosaicLayout": {
"columns": 12,
"tiles": [
{
"width": 6, "height": 4,
"widget": {
"title": "Requests per second by status class",
"xyChart": {
"dataSets": [{
"plotType": "STACKED_BAR",
"timeSeriesQuery": {
"timeSeriesFilter": {
"filter": "metric.type=\"run.googleapis.com/request_count\" resource.type=\"cloud_run_revision\" resource.label.\"service_name\"=\"catalog-api\"",
"aggregation": {
"alignmentPeriod": "60s",
"perSeriesAligner": "ALIGN_RATE",
"crossSeriesReducer": "REDUCE_SUM",
"groupByFields": ["metric.label.\"response_code_class\""]
}
}
}
}]
}
}
}
]
}
}
JSON
gcloud monitoring dashboards create --config-from-file=catalog-dashboard.json
gcloud monitoring dashboards list --format='table(displayName, name)'
Derived from Managing dashboards by API and gcloud monitoring dashboards create.
The quickest way to author a dashboard JSON is to build it in the console and use JSON → Copy in the dashboard’s toolbar, then keep that file in source control.
Notification channels
An alerting policy tells a channel who to contact. Channels include email, SMS, Slack, PagerDuty, webhooks, Pub/Sub and the mobile app. Create the channel first and keep its resource name.
In the Google Cloud console
-
Open Monitoring → Alerting → Edit notification channels (or Notification channels under Configure).
-
Pick a channel type, click Add new, and enter the address or authorise the integration (Slack asks for a workspace approval; webhooks accept basic auth or an HTTPS endpoint).
-
Email channels send a verification message; verify before relying on them.
With the gcloud CLI
gcloud beta monitoring channels create \
--display-name="Bookshelf on-call" \
--type=email \
--channel-labels=email_address=oncall@example.com
CHANNEL=$(gcloud beta monitoring channels list \
--filter='displayName="Bookshelf on-call"' --format='value(name)')
echo "$CHANNEL"
Derived from Notification options and gcloud beta monitoring channels create.
Alerting policies
An alerting policy has one or more conditions (a metric threshold, metric absence, a PromQL query, or a matched log entry), optional documentation shown in the notification, and the notification channels. A condition has a duration, so a single bad sample does not page anyone. When the condition holds, Monitoring opens an incident, notifies the channels, and closes the incident automatically once the condition clears.
Choose alerts for symptoms (error rate, latency, saturation, queue backlog), not for causes, and make each one actionable by linking a runbook in the documentation field.
In the Google Cloud console
-
Open Monitoring → Alerting and click Create policy.
-
Select a metric: search for Cloud Run Revision → Request count, then add a filter
service_name = catalog-apiandresponse_code_class = 5xx. -
Under Transform data, set Rolling window to 5 min and Rolling window function to rate.
-
Under Configure trigger, choose Threshold, Above threshold, and a value, for example
0.5requests per second. -
In Notifications and name, select the
Bookshelf on-callchannel, add documentation (symptom, dashboard link, first diagnostic step), name the policy catalog-api 5xx, and click Create policy.
With the gcloud CLI
cat > catalog-5xx-policy.json <<JSON
{
"displayName": "catalog-api 5xx",
"combiner": "OR",
"conditions": [{
"displayName": "5xx rate above 0.5 req/s for 5 minutes",
"conditionThreshold": {
"filter": "metric.type=\"run.googleapis.com/request_count\" resource.type=\"cloud_run_revision\" resource.label.\"service_name\"=\"catalog-api\" metric.label.\"response_code_class\"=\"5xx\"",
"aggregations": [{
"alignmentPeriod": "60s",
"perSeriesAligner": "ALIGN_RATE",
"crossSeriesReducer": "REDUCE_SUM"
}],
"comparison": "COMPARISON_GT",
"thresholdValue": 0.5,
"duration": "300s",
"trigger": { "count": 1 }
}
}],
"notificationChannels": ["$CHANNEL"],
"documentation": {
"mimeType": "text/markdown",
"content": "catalog-api returns 5xx. Check the Bookshelf dashboard, then Error Reporting for the new error group."
}
}
JSON
gcloud monitoring policies create --policy-from-file=catalog-5xx-policy.json
gcloud monitoring policies list --format='table(displayName, enabled, name)'
Derived from Create alerting policies, Manage alerting policies by API and gcloud monitoring policies create.
The heredoc above is unquoted so the shell expands $CHANNEL; the backslashes keep the inner double quotes. A
log-based alert uses conditionMatchedLog instead of a metric, which is cheaper to set up for rare events such as
"a secret was destroyed":
{
"displayName": "Secret version destroyed",
"combiner": "OR",
"conditions": [{
"displayName": "DestroySecretVersion audit entry",
"conditionMatchedLog": {
"filter": "protoPayload.methodName:\"DestroySecretVersion\""
}
}],
"alertStrategy": {
"notificationRateLimit": { "period": "3600s" },
"autoClose": "86400s"
},
"notificationChannels": ["projects/my-project-id/notificationChannels/1234567890"]
}
Derived from Configure log-based alerting policies.
A Terraform alternative for the metric alert:
resource "google_monitoring_alert_policy" "catalog_5xx" {
display_name = "catalog-api 5xx"
combiner = "OR"
conditions {
display_name = "5xx rate above 0.5 req/s"
condition_threshold {
filter = "metric.type=\"run.googleapis.com/request_count\" AND resource.type=\"cloud_run_revision\" AND resource.label.service_name=\"catalog-api\" AND metric.label.response_code_class=\"5xx\""
comparison = "COMPARISON_GT"
threshold_value = 0.5
duration = "300s"
aggregations {
alignment_period = "60s"
per_series_aligner = "ALIGN_RATE"
cross_series_reducer = "REDUCE_SUM"
}
}
}
notification_channels = [google_monitoring_notification_channel.oncall.name]
}
Derived from google_monitoring_alert_policy.
Alerting policies are listed per metrics scope, and each project has a quota on their number. Open incidents and their history are in Monitoring → Alerting; snooze a policy during planned maintenance rather than deleting it.
Uptime checks
An uptime check probes an HTTP, HTTPS or TCP endpoint from several regions (public checks) or from inside a VPC
(private checks, through a service directory endpoint) and records pass or fail as the metric
monitoring.googleapis.com/uptime_check/check_passed. Alert on it so you hear about an outage from Monitoring before
you hear about it from a customer.
In the Google Cloud console
-
Open Monitoring → Uptime checks and click Create uptime check.
-
Choose protocol HTTPS, resource type URL, and enter the host of the front end (
bookshelf.example.com) and path/. -
Set the check frequency (1 minute is typical), regions, and an optional response validation (status 200, content match).
-
Click Next, and on the alert step choose the
Bookshelf on-callchannel. Save.
With the gcloud CLI
gcloud monitoring uptime create bookshelf-front-end \
--resource-type=uptime-url \
--resource-labels=host=bookshelf.example.com,project_id="$PROJECT_ID" \
--protocol=https --path=/ --period=1 --regions=usa-oregon,europe,asia-pacific
gcloud monitoring uptime list-configs
Derived from Manage uptime checks and gcloud monitoring uptime create.
The check must be able to reach the endpoint. A site behind Cloud Armor or an IP allow list needs the uptime-check IP
ranges allowed (the list is downloadable from the console), and an internal-only service needs a private check.
Pair the check with an alerting policy on the check_passed metric, as in the previous section.
Service monitoring and SLOs
Service monitoring models your application as services and lets you set a service level objective (SLO) on a service level indicator (SLI) such as request-based availability ("97% of requests are not 5xx") or latency ("99% of requests are faster than 500 ms") over a rolling or calendar compliance period. Cloud Run, GKE (Istio and Cloud Service Mesh), App Engine and Cloud Endpoints services are detected automatically; others are defined as custom services. The error budget is the allowed failure that remains, and a burn-rate alert fires when the budget is being consumed faster than the period allows, which pages for fast burns and creates a ticket for slow burns.
-
Open Monitoring → Services and select
catalog-api. -
Click Create SLO, choose Availability or Latency, Request-based, a goal such as 99.5%, and a rolling period such as 28 days.
-
Save, then click Create SLO alert and choose a burn-rate condition (for example lookback 1 hour, threshold 10).
There is no gcloud monitoring slos command group; automate SLOs with the Service Monitoring API or Terraform
(google_monitoring_slo):
SERVICE_ID=$(curl -s -H "Authorization: Bearer $(gcloud auth print-access-token)" \
"https://monitoring.googleapis.com/v3/projects/$PROJECT_ID/services" | \
jq -r '.services[] | select(.displayName=="catalog-api") | .name | split("/") | last')
curl -s -X POST -H "Authorization: Bearer $(gcloud auth print-access-token)" \
-H "Content-Type: application/json" \
"https://monitoring.googleapis.com/v3/projects/$PROJECT_ID/services/$SERVICE_ID/serviceLevelObjectives?serviceLevelObjectiveId=catalog-availability" \
-d '{
"displayName": "catalog-api 99.5% availability, 28 days",
"goal": 0.995,
"rollingPeriod": "2419200s",
"serviceLevelIndicator": { "requestBased": { "goodTotalRatio": {
"badServiceFilter": "metric.type=\"run.googleapis.com/request_count\" resource.type=\"cloud_run_revision\" metric.label.\"response_code_class\"=\"5xx\"",
"totalServiceFilter": "metric.type=\"run.googleapis.com/request_count\" resource.type=\"cloud_run_revision\""
}}}
}'
Metrics from Spring Boot (Micrometer)
Spring Boot Actuator and Micrometer collect JVM, HTTP and datasource metrics; the Prometheus registry exposes them for scraping, and the OpenTelemetry registry can push them with OTLP. The general model, naming, custom meters and dashboard ideas are in Metrics and Observability: Micrometer, Actuator, and Distributed Tracing. On Google Cloud you have two good routes: scrape the Prometheus endpoint with Managed Service for Prometheus (next section), or push OTLP metrics to the Telemetry API (see OpenTelemetry below). Avoid the old Stackdriver Micrometer registry for new work.
Derived from Spring Boot Actuator metrics.
Managed Service for Prometheus
Google Cloud Managed Service for Prometheus (GMP) is a Prometheus-compatible store backed by Cloud Monitoring’s
global datastore (Monarch). You keep Prometheus exporters, /metrics endpoints, PromQL and Grafana, but you do not
run Prometheus servers, storage or federation. Prometheus metrics are stored under prometheus.googleapis.com/…
and are billed by samples ingested, so label cardinality and scrape interval are the cost levers. The model, metric
types, PromQL and Alertmanager are explained in Prometheus & Monitoring and
Prometheus architecture & ecosystem; this section covers what is specific to Google Cloud.
| Collection mode | Where it fits |
|---|---|
Managed collection |
The default on GKE Autopilot and on new Standard clusters. Google runs the collectors; you declare targets with
|
Self-deployed collection |
A Prometheus (or OpenTelemetry Collector) you run, with the GMP binary or the |
Cloud Run sidecar |
A Prometheus sidecar container scrapes the service on |
OpenTelemetry Collector |
The Collector’s |
Derived from Managed Service for Prometheus and Get started with managed collection.
Scraping catalog-api on GKE
Enable managed collection on an existing cluster and declare the scrape target:
gcloud container clusters update bookshelf-gke --location="$REGION" \
--enable-managed-prometheus
Derived from Enable managed collection on GKE.
apiVersion: monitoring.googleapis.com/v1
kind: PodMonitoring
metadata:
name: catalog-api
namespace: bookshelf
spec:
selector:
matchLabels:
app: catalog-api
endpoints:
- port: http
path: /actuator/prometheus
interval: 30s
Derived from Set up managed collection: PodMonitoring.
kubectl apply -f catalog-podmonitoring.yaml
kubectl get podmonitoring -n bookshelf
Derived from Set up managed collection.
The Pod’s service account needs roles/monitoring.metricWriter, which on GKE with Workload Identity Federation is
granted to the Kubernetes service account’s principal (see Deploying Microservices on GKE). Metrics
appear in Monitoring → Metrics Explorer in PromQL mode within a minute or two.
Querying and alerting with PromQL
Cloud Monitoring understands PromQL natively in Metrics Explorer, dashboards and alerting policies
(conditionPrometheusQueryLanguage). External tools such as Grafana connect to the Prometheus-compatible query API
with an access token or a service account:
curl -s -H "Authorization: Bearer $(gcloud auth print-access-token)" \
"https://monitoring.googleapis.com/v1/projects/$PROJECT_ID/location/global/prometheus/api/v1/query" \
--data-urlencode 'query=sum(rate(http_server_requests_seconds_count{status=~"5.."}[5m]))'
Derived from Query using Cloud Monitoring and PromQL and Query using the Prometheus HTTP API.
Rule evaluation can be managed (Rules custom resource) or done in Cloud Monitoring alerting policies; recording
rules, alert rules and Alertmanager routing are in Recording & alerting rules and
Alertmanager. Kubernetes-specific monitoring patterns (kube-state-metrics, cAdvisor)
are in Containers & Kubernetes monitoring. For Grafana on top of GMP see
Grafana: Dashboards & visualization; Google Cloud Monitoring is also available as a
Grafana data source.
Cloud Trace
Cloud Trace records how a request travels through your services as a tree of timed spans, so a slow
GET /books can be broken down into the gateway, catalog-api, the database call and a downstream HTTP call. Cloud
Run, App Engine and the load balancer already create or forward trace context; your application must propagate it and
may add its own spans. Since 2025 the recommended way to send traces is OpenTelemetry with OTLP, described in
the next section, rather than the older Trace exporter libraries.
In the Google Cloud console
-
Open Observability → Trace → Trace Explorer.
-
Filter by service (
catalog-api), span name, latency range or an attribute, and pick a point on the scatter plot. -
Click a trace to see the waterfall; select a span to see attributes, events and the linked log entries (they match by the
logging.googleapis.com/tracefield).
With the gcloud CLI
Trace has no day-to-day CLI; the API is the programmable surface:
curl -s -H "Authorization: Bearer $(gcloud auth print-access-token)" \
"https://cloudtrace.googleapis.com/v1/projects/$PROJECT_ID/traces?view=ROOTSPAN&pageSize=5"
Derived from Cloud Trace overview and Cloud Trace API: traces.list.
Latency sampling is the cost lever: trace a fraction of requests (for example 10%) with Micrometer’s
management.tracing.sampling.probability rather than all of them.
OpenTelemetry on Google Cloud
OpenTelemetry (OTel) is the vendor-neutral standard for traces, metrics and logs. Google Cloud accepts OTel data
through the Telemetry API (telemetry.googleapis.com), which exposes an OTLP endpoint authenticated with
Application Default Credentials. Because the application only knows OTLP, you can move between Google Cloud and
another backend by changing the endpoint. Verify which signals are generally available for your region on the
Telemetry API page, since support for metrics and logs over OTLP has been rolling out after traces.
There are three common wiring options, in rising order of effort and control:
-
Direct from the application: the SDK or the OpenTelemetry Java agent exports OTLP straight to
telemetry.googleapis.com, using the workload’s service account. -
Via the OpenTelemetry Collector: a sidecar or a Deployment receives OTLP, batches and adds resource attributes (
k8s.pod.name,cloud.region), and exports to Google Cloud with thegooglecloudorotlphttpexporter. -
Automatic platform support: Cloud Run has a managed OpenTelemetry sidecar pattern, and GKE offers managed OpenTelemetry collection; both are still evolving, so check the launch stage before standardising on them.
Derived from Telemetry (OTLP) API overview and OpenTelemetry Collector with Google Cloud.
Spring Boot with Micrometer Tracing
Spring Boot’s tracing support bridges Micrometer to OpenTelemetry. Add the bridge and the OTLP exporter, point it at the Telemetry API, and let Application Default Credentials provide the token:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
<dependency>
<groupId>io.micrometer</groupId>
<artifactId>micrometer-tracing-bridge-otel</artifactId>
</dependency>
<dependency>
<groupId>io.opentelemetry</groupId>
<artifactId>opentelemetry-exporter-otlp</artifactId>
</dependency>
<dependency>
<groupId>com.google.cloud.opentelemetry</groupId>
<artifactId>exporter-auto</artifactId>
<version>${opentelemetry-operations.version}</version>
</dependency>
management.tracing.sampling.probability=0.1
management.otlp.tracing.endpoint=https://telemetry.googleapis.com/v1/traces
spring.application.name=catalog-api
Derived from Spring Boot tracing and opentelemetry-operations-java.
The exporter-auto module (from the Google Cloud OpenTelemetry operations library) supplies the credential
handling; Google’s Telemetry API page documents the exact authenticator settings for the OTLP exporter in use, so
follow it for the version you adopt. For a quick try without code changes, the OpenTelemetry Java agent attaches at
start-up:
java -javaagent:/opt/otel/opentelemetry-javaagent.jar \
-Dotel.service.name=catalog-api \
-Dotel.traces.exporter=otlp \
-Dotel.exporter.otlp.endpoint=http://localhost:4317 \
-jar catalog-api.jar
Derived from OpenTelemetry Java agent: getting started.
In the example the agent talks to a local Collector on port 4317, which is the safer pattern when several services share one exporter configuration. A minimal Collector configuration:
receivers:
otlp:
protocols:
grpc: {}
http: {}
processors:
batch: {}
resourcedetection:
detectors: [gcp]
exporters:
googlecloud: {}
googlemanagedprometheus: {}
service:
pipelines:
traces:
receivers: [otlp]
processors: [resourcedetection, batch]
exporters: [googlecloud]
metrics:
receivers: [otlp]
processors: [resourcedetection, batch]
exporters: [googlemanagedprometheus]
The workload’s service account needs roles/cloudtrace.agent for traces and roles/monitoring.metricWriter for
metrics. Keep the log correlation intact: with Micrometer Tracing the trace and span ids are placed in the MDC, and
the gcp structured log format writes them as logging.googleapis.com/trace so that Logs Explorer shows View trace
details on each entry.
Cloud Profiler
Cloud Profiler continuously samples CPU time, wall time, heap and allocations from running production code with low overhead (typically a few percent), and shows the result as a flame graph aggregated over time and across instances. It answers "which method is burning CPU" without attaching a debugger. Profiler is available for Java, Go, Python and Node.js; the service itself is free of charge. Enable it in the application; there is nothing to install in the platform.
# Dockerfile fragment for catalog-api (Java): install the agent into the image
mkdir -p /opt/cprof && \
curl -sL https://storage.googleapis.com/cloud-profiler/java/latest/profiler_java_agent.tar.gz \
| tar xzv -C /opt/cprof
# Start the JVM with the agent
java -agentpath:/opt/cprof/profiler_java_agent.so=-cprof_service=catalog-api,-cprof_service_version=1.0.0 \
-jar catalog-api.jar
# Allow the service account to upload profiles
gcloud projects add-iam-policy-binding "$PROJECT_ID" \
--member="serviceAccount:catalog-api-sa@$PROJECT_ID.iam.gserviceaccount.com" \
--role=roles/cloudprofiler.agent
Derived from Profiling Java applications and About Cloud Profiler.
Open Observability → Profiler, pick the service catalog-api, the profile type (CPU, Heap, Wall time,
Allocated heap) and a version, and read the flame graph: wide frames are expensive. Use Compare to to check a
new version against the previous one after a release. Cloud Run needs the CPU to be available while the request is not
being handled for background sampling to work well; with request-based CPU allocation profiles are sparse, so prefer
instance-based CPU (see Cloud Run Scaling, Traffic and Jobs) for services you intend to
profile.
Error Reporting
Error Reporting counts, groups and displays the exceptions your services log, so that a thousand identical
stack traces become one error group with a count, first and last seen time, affected services and versions, and a
link to the log entry. It works automatically for logs from Cloud Run, GKE, App Engine, Compute Engine (with the Ops
Agent) and Cloud Run functions when the entry contains a stack trace in the payload or a @type of
type.googleapis.com/google.devtools.clouderrorreporting.v1beta1.ReportedErrorEvent.
In the Google Cloud console
-
Open Observability → Error Reporting.
-
The list shows error groups by occurrences; click one to see the stack trace, a histogram, the affected versions and sample log entries.
-
Set a status (Acknowledged, Resolved, Muted) and link a bug-tracker issue. A resolved group that recurs re-opens and can notify you.
-
Open Configure notifications to receive an email or mobile push for new errors.
With the gcloud CLI
# Report a test event so a group appears
gcloud beta error-reporting events report \
--service=catalog-api --service-version=1.0.0 \
--message='java.lang.IllegalStateException: demo
at com.example.bookshelf.CatalogService.find(CatalogService.java:42)'
# List recent events
gcloud beta error-reporting events list --service=catalog-api --limit=10
Derived from Formatting error messages and gcloud beta error-reporting events report.
Logging an exception with its stack trace (log.error("lookup failed", ex)) in the gcp structured format is
enough for Spring Boot services; no extra library is required. Error Reporting alerts are free of charge and send
mail rather than pages; for paging, create a log-based or metric alert on the same log filter. The error counts depend
on the logs being stored, so an exclusion that drops ERROR entries also hides errors.
Ops Agent on virtual machines
Compute Engine VMs emit only hypervisor-level metrics (CPU, disk and network) by default. The Ops Agent is the single agent that adds memory, disk usage, process metrics and log collection (syslog, application files), based on Fluent Bit for logs and the OpenTelemetry Collector for metrics. It replaces the legacy Logging and Monitoring agents, which are no longer supported.
# On the VM (Linux): install the Ops Agent
curl -sSO https://dl.google.com/cloudagents/add-google-cloud-ops-agent-repo.sh
sudo bash add-google-cloud-ops-agent-repo.sh --also-install
sudo systemctl status google-cloud-ops-agent*
Derived from Install the Ops Agent.
For a fleet use an agent policy or the VM Manager OS policy so that every VM in a project or label set gets the
agent automatically, and customise collection in /etc/google-cloud-ops-agent/config.yaml (for example a file receiver
for an application log). The VM’s service account needs roles/logging.logWriter and roles/monitoring.metricWriter.
Compute Engine itself, instance groups and start-up scripts are in Compute Engine; GKE
and Cloud Run do not need the agent.
Derived from Configure the Ops Agent.
Cloud Debugger shutdown and debugging today
Cloud Debugger, which took production snapshots and injected logpoints into running Java, Python, Go and Node.js
applications, was shut down on 2023-05-31. Its open-source successor, Snapshot Debugger, was archived on
2023-09-07. Older guides, including those for the App Engine flexible environment’s debug mode, still describe the
Debugger and its gcloud debug commands; none of them work any longer. Use the following instead.
| Need | Current approach |
|---|---|
See what happened at a given time |
Structured logs with a correlation id and trace id in Logs Explorer; log-based metrics for counts. |
Find which line throws |
Error Reporting groups with full stack traces. |
Find why a request is slow |
Cloud Trace for the call tree; Cloud Profiler for hot methods. |
Inspect a live container |
|
Step through code |
Reproduce locally with the Cloud Code debugger (see Developer Tools and DevOps) or attach a remote JVM debugger over a port-forward to a non-production workload. |
Derived from Cloud Debugger deprecation and Observability for GKE.
Pricing and cost drivers
Pricing changes; the linked page is the source of truth and values here are deliberately not quoted (pricing page checked 2026-09-30).
-
Cloud Logging is billed on log volume ingested into buckets beyond a monthly free allotment per project, and on storage retained beyond the free retention period of a bucket.
_Required(audit Admin Activity) is free. Routing a log to another project’s bucket or to BigQuery or Cloud Storage incurs the destination’s costs as well. Exclusions, shorter retention and dropping debug logs are the main controls. -
Cloud Monitoring system metrics from Google Cloud services are free. Custom, external and Prometheus metrics are billed per sample or per volume ingested, so reduce scrape interval, drop unused series and avoid high-cardinality labels (user id, order id). Alerting policies, uptime checks, dashboards and SLOs have allotments or are free; check the page for notification channels such as SMS.
-
Cloud Trace is billed per span ingested above a monthly free allotment; sampling lowers it.
-
Cloud Profiler and Error Reporting have no charge of their own, apart from the logs behind Error Reporting.
-
Log Analytics querying uses a free allotment of slots, with no extra charge for the upgrade of a bucket.
Derived from Google Cloud Observability pricing and Logging quotas and limits.
Quotas that matter in practice: entries must be below 256 KiB each, the write rate and the number of read requests per minute are limited per project, a project can have up to 200 log-based metrics and 200 user-defined buckets, and each metrics scope has limits on alerting policies and uptime checks. All are listed on the linked quota pages and can be raised from IAM & Admin → Quotas.
Recent changes worth knowing
| Date | Change |
|---|---|
2023-05-31 |
Cloud Debugger shut down. |
2023-09-07 |
Snapshot Debugger repository archived. |
2024 |
Log Analytics became generally available, with linked BigQuery datasets. |
2025 |
Telemetry (OTLP) API introduced for traces; OpenTelemetry named the preferred instrumentation path. |
2026 |
PromQL is the recommended query language in Cloud Monitoring; MQL is on a deprecation path for new alerting. |
Derived from Google Cloud Observability release notes and Cloud Logging release notes.
Troubleshooting
-
No logs from a Cloud Run service. Check that the container writes to stdout/stderr, that the service account has
roles/logging.logWriter, and that an exclusion on_Defaultis not dropping the entries. -
Sink created but destination empty. The writer identity lacks permission on the destination, or the filter does not match;
gcloud logging sinks describeshows the identity, and the destination’s Logs routing errors appear inlogging.googleapis.com/sink_errorentries. -
Alert never fires. The metric has no data (wrong filter, wrong resource type) or the duration is longer than the condition holds; chart the same filter in Metrics Explorer first.
-
No traces. The exporter lacks
roles/cloudtrace.agent, sampling is0, or the Telemetry API is not enabled. -
Managed collection scrapes nothing. The
PodMonitoringselector does not match the Pod labels, the port name differs, or the Pod’s service account cannot write metrics. -
Bill grew suddenly. Open the Logging Logs Storage page and the Monitoring Metrics Diagnostics page to rank sources, then exclude, sample or reduce retention.
Derived from Troubleshoot routing and sinks and Troubleshoot alerting.
Clean up
Remove in dependency order; observability resources are cheap to leave, but log buckets keep data and incur storage until deleted.
gcloud monitoring policies delete "$(gcloud monitoring policies list \
--filter='displayName="catalog-api 5xx"' --format='value(name)')" --quiet
gcloud monitoring uptime delete "$(gcloud monitoring uptime list-configs \
--filter='displayName="bookshelf-front-end"' --format='value(name)')" --quiet
gcloud beta monitoring channels delete "$CHANNEL" --quiet
gcloud monitoring dashboards delete "$(gcloud monitoring dashboards list \
--filter='displayName="Bookshelf catalog-api"' --format='value(name)')" --quiet
gcloud logging metrics delete orders_failed --quiet
gcloud logging links delete bookshelf_audit_link --bucket=bookshelf-audit --location=global --quiet
gcloud logging sinks delete errors-to-bq --quiet
gcloud logging sinks delete audit-to-bucket --quiet
gcloud logging sinks update _Default --remove-exclusions=drop-health-checks
bq rm -r -f -d "$PROJECT_ID:bookshelf_errors"
gcloud logging buckets delete bookshelf-audit --location=global --quiet
Derived from gcloud logging buckets delete and gcloud monitoring policies delete.
A deleted log bucket enters a 7-day pending-deletion state and can be restored with gcloud logging buckets undelete
during that time; a bucket whose retention is locked cannot be deleted until its retention has elapsed, which is why the
lock is reserved for compliance archives. Deleting a throwaway project removes all of the above at once.
Related pages
-
Logging: Logback Defaults, Structured Output, and Container-Friendly Routing — Spring Boot logging configuration, levels and structured output.
-
Metrics and Observability: Micrometer, Actuator, and Distributed Tracing — Actuator, Micrometer and tracing in Spring Boot.
-
Resources, Logging and Monitoring — container logging drivers and resource metrics.
-
Prometheus & Monitoring — the Prometheus reference: data model, PromQL, Alertmanager, Grafana.
-
Recording & alerting rules — recording and alert rules.
-
Cloud Run — Bookshelf services whose logs and metrics appear here.
-
GKE Clusters and Deploying Microservices on GKE — GKE logging and Managed Prometheus.
-
Governance, Security and Compliance — audit logs, aggregated sinks and organisation policy.
-
Cost Management and Billing — budgets and alerts on spend, billing export.
-
Identity and Access — service accounts and roles used by agents and exporters.
-
Monitoring and Observability and Azure — the AWS and Azure counterparts.