# Logs, metrics and alerts for a Cloud Run app: what you get for free and the three alerts to set up

> Cloud Run sends requests, logs and metrics to Google Cloud with no setup. The log format Google reads, where to look, three alerting policies as files, and what each part costs.

Published 2026-10-12 · Updated 2026-10-13 · [By Exodus team](https://exodus.elim.io/about) · Operations
<https://exodus.elim.io/blog/logs-metrics-and-alerts-for-a-cloud-run-app>

Cloud Run logs every request and every line a container prints, and keeps metrics on requests, latency and instances, free, with no setup. It tells nobody when something breaks. Three alerting policies cover most outages of a small app: an uptime check on a health path, a threshold on 5xx responses, and a log match on entries at `ERROR` or above. A small app pays $0 for this.

## In short

- Print one JSON object per line with `severity` and `message`; a `level` field is not read, and 58 of 59 such entries of ours arrived with no severity.
- Logs are free up to 50 GiB per project per month, then $0.50 per GiB, and are kept 30 days by default.
- The request log Cloud Run writes was 82% of what our services logged, about 770 bytes per request.
- The three alerts: an uptime check from 3 regions every 5 minutes, more than 5 responses 5xx in 5 minutes, and an error log match capped at one email an hour.
- Alerting is free until at least September 1, 2027; after that, a typical metric alert costs about $0.39 a month.

Prices are Google's list prices, read on October 12, 2026.

## What Cloud Run collects without you

Google's logging page lists three kinds of logs that Cloud Run sends to Cloud Logging, Google's log store, on its own:

- **Request logs.** One entry per request to a service: method, URL, status, latency, size, user agent, the revision that answered. Cloud Run writes them; your code does not.
- **Container logs.** Whatever your code writes to stdout or stderr, to files under `/var/log`, to syslog, or through Google's logging client libraries. Each entry is tagged with the service, the revision and the region.
- **System logs.** Platform messages, under the log name `varlog/system`. The useful ones say why an instance started: `Starting new instance. Reason: AUTOSCALING`, `DEPLOYMENT_ROLLOUT`, or `MANUAL_OR_CUSTOMER_MIN_INSTANCE`, the last from a [minimum instances setting](https://exodus.elim.io/blog/min-instances-and-startup-cpu-boost).

Cloud Monitoring, Google's metrics store, gets Cloud Run's metrics with "no setup or configuration required" and no charge. Error Reporting, also free, groups exceptions with a stack trace found in your logs, plus Cloud Run's "Memory limit exceeded" and "No instances available" errors. Cloud Trace gets the traces Cloud Run makes for requests, also at no charge.

![A diagram in three lanes. In your container, your code prints to stdout and stderr. In Cloud Run, a request log with one entry per request, and metrics every 60 seconds at no charge. In Cloud Logging and Cloud Monitoring, log lines and the request log go to the Log Router, where exclusions drop entries, and on to the _Default bucket, kept 30 days. A highlighted alert policy receives log matches from the Log Router and thresholds from the metrics, and notifies you by email, Slack or PagerDuty.](https://exodus.elim.io/media/v2026-09-16/t/exodus/assets/image-19c22144f5ae46cba548dbec5c4232279ce441acd632325f6b44083cb3ca2ea2-680x440-svg/bytes "Where logs and metrics go, and the two ways an alert is made: from log entries or from metrics.")

The Log Router decides where every entry goes. Each project has two buckets: `_Required` keeps audit logs of administrative actions for 400 days at no charge, and `_Default` keeps everything else for 30 days.

## Write logs Google can read

Cloud Run looks at each line your container prints. A line that is a complete JSON object becomes a structured entry, `jsonPayload`, whose fields you can filter on. Any other line becomes `textPayload`, a string. A few JSON fields are taken out and used by Cloud Logging itself:

- `severity`: the entry's level. Use `DEBUG`, `INFO`, `NOTICE`, `WARNING`, `ERROR`, `CRITICAL`. Without it, the entry has no severity, which the console shows as "Default".
- `message`: the text the console shows on the entry's line.
- `logging.googleapis.com/trace`: ties the line to the request it belongs to, so that the console nests your lines under the request log entry.

A request handler in Node.js that logs this way:

```ts
function log(severity, message, req, extra = {}) {
  const entry = { severity, message, ...extra };
  const header = req?.get("X-Cloud-Trace-Context");
  if (header && process.env.GOOGLE_CLOUD_PROJECT) {
    const [trace] = header.split("/");
    entry["logging.googleapis.com/trace"] =
      `projects/${process.env.GOOGLE_CLOUD_PROJECT}/traces/${trace}`;
  }
  console.log(JSON.stringify(entry));
}

log("ERROR", "payment failed", req, { orderId: 1042, code: "card_declined" });
```

Pass the project ID with `--set-env-vars GOOGLE_CLOUD_PROJECT=my-project` on deploy, or leave the trace out. In Python, `print(json.dumps({...}))` does the same; set `PYTHONUNBUFFERED=1` so lines are not held in a buffer. Most logging libraries have a JSON output; check what they call the level field.

That last check matters more than it looks. Many libraries write the level as `level`, not `severity`. Cloud Logging does not read `level`, so every entry arrives with no severity, and a filter on `severity>=ERROR` finds nothing. We checked our own project, read-only:

![A terminal with three gcloud logging read commands and their counts. Request logs over 7 days: 63 entries with no severity and status 1xx, 5315 INFO with 2xx, 574 INFO with 3xx, 2027 WARNING with 4xx, 21 ERROR with 5xx. Stdout over 2 days: 1714 plain text lines with no severity, 5 JSON lines at INFO. Entries with a level field over 30 days: 2 with level ERROR, 49 INFO and 7 WARN all have no severity; 1 entry has severity ERROR.](https://exodus.elim.io/media/v2026-09-16/t/exodus/assets/image-19c8bf71e22eb496743fdfe0c75762c413ece99e5775e1bf388f5bd31ba44c5d-680x576-svg/bytes "Our project, read-only: request logs get a severity from the status code; our own lines mostly do not.")

Exodus team: three things came out of it. Request logs carry a severity that follows the status: `INFO` for 2xx and 3xx, `WARNING` for 4xx, `ERROR` for 5xx, and none for WebSocket upgrades (101). Of 1,719 lines our services printed to stdout in two days, 1,714 were plain text with no severity. And one service logs JSON with a `level` field: 58 of its 59 entries had no severity, so our one alerting policy for it matches `jsonPayload.level="ERROR"` as well as `severity>=ERROR`. Fixing the field name in the logger is the better cure.

## Read logs from the command line

The console's Logs tab shows request and container logs together. From a terminal:

```shell
gcloud run services logs read my-app --region europe-west1 --limit 50
```

It reads the last day by default. To follow logs live, `gcloud beta run services logs tail my-app` works; Google marks it as Preview, and it installs the `log-streaming` component the first time.

For real queries, use `gcloud logging read`:

```shell
# errors of one service in the last hour
gcloud logging read 'resource.type="cloud_run_revision"
  AND resource.labels.service_name="my-app"
  AND severity>=ERROR' --freshness=1h --limit=50

# 5xx responses with their URLs
gcloud logging read 'resource.labels.service_name="my-app"
  AND httpRequest.status>=500' --freshness=1d \
  --format="value(timestamp,httpRequest.status,httpRequest.requestUrl)"
```

Your JSON fields are searchable as `jsonPayload.orderId=1042`; a colon means "contains", as in `textPayload:"timeout"`. The same queries per release, filtered on `resource.labels.revision_name`, are in the guide on [revisions, traffic splitting and rollbacks](https://exodus.elim.io/blog/revisions-traffic-splitting-and-rollbacks). Querying logs is not charged.

## The metrics that matter

For a web app, six of Cloud Run's metrics answer most questions:

- `request_count`: requests per revision, with labels `response_code` and `response_code_class` (2xx, 4xx, 5xx). Errors per minute come from here.
- `request_latencies`: milliseconds from the request reaching your container to the response, read as percentiles (p50 is the median, p95 the latency 95% of requests beat).
- `container/instance_count`: how many instances exist, broken down by state (active or idle).
- `container/cpu/utilizations` and `container/memory/utilizations`: how close instances run to their limits. Memory near 100% ends in "Memory limit exceeded" and a restarted instance.
- `container/startup_latencies`: how long new instances take to start, the cold start.
- `container/billable_instance_time`: the time you pay for.

Every name starts with `run.googleapis.com/`. Each is sampled every 60 seconds and visible after up to 120 seconds, so charts lag by two or three minutes. They are in the service's Metrics tab, or in Metrics Explorer under "Cloud Run Revision".

Two details in Google's metric list decide what an alert can see. `request_count` excludes requests that never reached an instance, for example unauthorized ones or those refused because the service hit its maximum number of instances; those appear only in the request log. And `request_latencies` does not include the time an instance takes to start, so a slow cold start shows in `startup_latencies`, not in latency.

Latency misleads on services that hold connections open. Exodus team: on one of our services that serves WebSockets, p95 latency in five-minute windows reached 3,855 seconds over a week, because a WebSocket "request" lasts as long as the connection. Leaving out the 101 responses still left 16 of 44 windows above one second, from long streams. A latency alert there would fire all day; watch 5xx and uptime instead (see [WebSockets and SSE](https://exodus.elim.io/blog/websockets-and-sse-on-cloud-run)).

## Three alerts for a small app

An alerting policy is a condition plus notification channels. The condition watches a metric (a threshold) or matches log entries (a log match). For a small app, three policies catch most outages:

![Three numbered cards. 1, is it up: an uptime check runs GET /health from 3 regions every 5 minutes and fires when checks fail for 10 minutes; 25,920 checks a month are free, and an alert on uptime metrics is free. 2, highlighted, is it failing: a threshold on request_count with response_code_class 5xx fires at more than 5 in 5 minutes; free until at least September 1, 2027, then about $0.39 a month. 3, did it log an error: a log match on severity at ERROR or above sends at most one email an hour; free until at least September 1, 2027, and log match returns no points.](https://exodus.elim.io/media/v2026-09-16/t/exodus/assets/image-ea5a896e8ab9f55867652830ac3eb79dc103a409ff746967d9333dd7703490ff-680x344-svg/bytes "Three alerts that cover most outages of a small app, and what each costs.")

### Step 0: a notification channel

A channel is where alerts go: email, the Google Cloud mobile app, PagerDuty, SMS, Slack, webhooks, Pub/Sub or Google Chat. Google warns that delivery to SMS and Slack is not guaranteed. Start with email:

```shell
gcloud beta monitoring channels create \
  --display-name="On call (email)" --type=email \
  --channel-labels=email_address=oncall@example.com
gcloud beta monitoring channels list --format="value(name,displayName)"
```

The second command prints the channel's full name, which starts with `projects/` and ends with the channel ID; the policies below need it. Send a test notification from the console to see that it is not filtered as spam.

### Alert 1: is it up?

An uptime check requests a URL from Google's checkers in several regions and records whether it passed. It catches what the service cannot report itself: a broken domain, a crash loop, a deploy that serves nothing.

```shell
gcloud monitoring uptime create my-app-health \
  --resource-type=uptime-url \
  --resource-labels=host=my-app.example.com,project_id=PROJECT_ID \
  --protocol=https --path=/health --period=5 \
  --regions=europe,usa-oregon,usa-virginia
```

Per gcloud's help, a check needs at least three regions (default: all six), runs every 1, 5, 10 or 15 minutes (default 1), and times out after 60 seconds. For a private service, add `--service-agent-auth=oidc-token`. Avoid paths ending in `z`, such as `/healthz`, which Cloud Run reserves (see [health checks and startup probes](https://exodus.elim.io/blog/health-checks-and-startup-probes)).

The command prints the check's name; its last part is the `CHECK_ID`. Then the alert, in a file `alert-uptime.json`, taken from Google's sample policy:

```json
{
  "displayName": "my-app: health check failing",
  "combiner": "OR",
  "conditions": [{
    "displayName": "uptime check my-app-health fails",
    "conditionThreshold": {
      "filter": "metric.type=\"monitoring.googleapis.com/uptime_check/check_passed\" AND metric.label.check_id=\"CHECK_ID\" AND resource.type=\"uptime_url\"",
      "aggregations": [{"alignmentPeriod": "1200s",
        "perSeriesAligner": "ALIGN_NEXT_OLDER",
        "crossSeriesReducer": "REDUCE_COUNT_FALSE",
        "groupByFields": ["resource.label.*"]}],
      "comparison": "COMPARISON_GT", "thresholdValue": 1,
      "duration": "600s", "trigger": {"count": 1}
    }
  }],
  "notificationChannels": ["projects/PROJECT_ID/notificationChannels/CHANNEL_ID"]
}
```

It fires when more than one region reports a failure for ten minutes, so one checker's bad minute wakes nobody. Create it with `gcloud monitoring policies create --policy-from-file=alert-uptime.json`. Each check is a real request: three regions every five minutes make 25,920 a month, within Cloud Run's 2 million free requests.

### Alert 2: is it failing?

The 5xx threshold watches `request_count` and fires when the service answers with server errors. Save as `alert-5xx.json`:

```json
{
  "displayName": "my-app: 5xx responses",
  "combiner": "OR",
  "conditions": [{
    "displayName": "more than 5 responses 5xx in 5 minutes",
    "conditionThreshold": {
      "filter": "resource.type=\"cloud_run_revision\" AND resource.labels.service_name=\"my-app\" AND metric.type=\"run.googleapis.com/request_count\" AND metric.labels.response_code_class=\"5xx\"",
      "aggregations": [{"alignmentPeriod": "300s",
        "perSeriesAligner": "ALIGN_DELTA",
        "crossSeriesReducer": "REDUCE_SUM",
        "groupByFields": ["resource.label.service_name"]}],
      "comparison": "COMPARISON_GT", "thresholdValue": 5,
      "duration": "0s", "trigger": {"count": 1}
    }
  }],
  "alertStrategy": {"autoClose": "1800s"},
  "notificationChannels": ["projects/PROJECT_ID/notificationChannels/CHANNEL_ID"]
}
```

It sums 5xx responses of all revisions over five minutes and fires above 5. Pick the number from your own traffic. Exodus team: we ran this filter and aggregation over a week of our eight services, read-only; it would have fired twice, at 6 and 7 errors. A threshold of 0 would have fired in 10 windows. For a busy service, a ratio of 5xx to all requests is steadier; Google's sample policies show one with `denominatorFilter`.

### Alert 3: did it log an error?

A log match fires on a single entry, which suits errors that do not end in a 5xx: a failed payment (see [Stripe webhooks on Cloud Run](https://exodus.elim.io/blog/stripe-webhooks-on-cloud-run)), a job that gave up, an exception in a background task. Save as `alert-errors.json`:

```json
{
  "displayName": "my-app: error in the logs",
  "combiner": "OR",
  "conditions": [{
    "displayName": "a log entry at ERROR or above",
    "conditionMatchedLog": {
      "filter": "resource.type=\"cloud_run_revision\" AND resource.labels.service_name=\"my-app\" AND severity>=ERROR"
    }
  }],
  "alertStrategy": {"notificationRateLimit": {"period": "3600s"},
    "autoClose": "1800s"},
  "notificationChannels": ["projects/PROJECT_ID/notificationChannels/CHANNEL_ID"]
}
```

`notificationRateLimit` caps notifications at one an hour, so a loop of errors sends one email, not a thousand. `autoClose` closes the alert after 30 minutes without matches (default 7 days, minimum 30 minutes). A log-based policy has one condition and cannot count; for "more than 10 errors a minute", create a log-based metric with `gcloud logging metrics create` and put a threshold on it. If your logger writes `level`, add `OR jsonPayload.level="ERROR"`, as we had to. 5xx request logs are at `ERROR` too, so this policy also fires on server errors.

Create both with `gcloud monitoring policies create --policy-from-file=FILE`. To see a log match fire, Google's page points a policy at a test log and writes to it:

```shell
gcloud logging write test-log --severity=ERROR \
  --payload-type=text 'This log entry contains Oops'
```

### When an alert arrives

Google's alerting page says most metrics become visible after about 60 seconds and policy computation adds up to 5 minutes 30 seconds, plus the channel's own delay: expect a metric alert two to seven minutes after a problem starts. Put the first command to run into the policy's `documentation` field, so the email carries it.

## What it costs

List prices from Google's observability pricing page, read October 12, 2026:

- **Logs:** $0.50 per GiB written to a bucket, which includes 30 days of storage. The first 50 GiB per project per month are free. Reading and querying logs costs nothing, and the `_Required` bucket costs nothing.
- **Keeping logs longer:** $0.01 per GiB per month past 30 days.
- **Cloud Run metrics:** free. Your own metrics, including log-based metrics, are $0.2580 per MiB after the first 150 MiB per billing account; a counter point is 8 bytes, so one counter written every minute is about 0.33 MiB a month.
- **Uptime checks:** $0.30 per 1,000 executions after 1 million per project each month. One check every minute from all six regions is 259,200 executions; three such checks are free, a fourth makes the month $11.04.
- **Alerting:** free today. From no sooner than September 1, 2027, $0.35 a month per metric in a policy plus $0.50 per million points its query returns. A condition that returns one point every 30 seconds returns 86,400 points a month, $0.04, so alert 2 would cost about $0.39 a month. Policies on uptime metrics are not charged, and log-match conditions return no points.

The log line dominates, and inside it, the request log. Exodus team: over 30 days to October 12, 2026, our eight services handled 19,719 requests and wrote 17.7 MiB of logs; the request log was 14.5 MiB of it, about 770 bytes per request.

![A bar chart of log volume by log over 30 days for our eight services. Request logs 14.5 MiB, 82%. stdout 1.5 MiB, 8%. stderr 0.9 MiB, 5%. System logs 0.8 MiB, 5%.](https://exodus.elim.io/media/v2026-09-16/t/exodus/assets/image-e9dd9e3f753fce719e92ff553ce8dfe17babc25250506b71674816a78f90c5ba-680x340-svg/bytes "Our project, 30 days: the request log Cloud Run writes is most of the volume.")

At 770 bytes a request, the free 50 GiB covers about 70 million requests a month, roughly 2.3 million a day, before your own lines. A worked example: an app with 100,000 requests a day writes about 2.15 GiB of request logs a month; with two lines of 200 bytes per request from your code, about 3.3 GiB. That is $0. At 3 million requests a day the request log alone is 64.6 GiB, so 14.6 GiB over the allowance, $7.30 a month.

## Keeping the log bill down

Act only when the bill shows Cloud Logging growing (see [budget alerts and the billing export](https://exodus.elim.io/blog/budget-alerts-and-the-billing-export)).

**Do not log every request yourself.** Cloud Run already does. Exodus team: one of our services, a static site behind nginx, wrote an access line per request to stdout on top of Cloud Run's request log. Over 30 days its stdout was 0.86 MiB against 0.77 MiB of request logs, and nginx notices on stderr added 0.75 MiB, so it wrote about three times the log volume its requests alone needed. Turning off the access log in the server or the framework is a one-line change.

**Exclude what you never read.** A sink is a rule that sends matching entries to a bucket; `_Default` feeds the `_Default` bucket. An exclusion filter on it drops matching entries before they are stored, and you do not pay for them:

```shell
gcloud logging sinks update _Default --add-exclusion='name=health-checks,filter=log_id("run.googleapis.com/requests") AND httpRequest.requestUrl:"/health"'
```

An exclusion can keep a share instead of dropping everything: `sample(insertId, 0.9)` matches about 90% of entries, so an exclusion with that filter keeps the other 10% (on our request logs, `sample(insertId, 0.1)` returned 461 of 4,929 entries). Log-based alerts do not see excluded entries, and the bucket never stores them, so never exclude warnings or errors.

**Lower the noise at the source.** `DEBUG` lines in production, whole request bodies, a stack trace per retry: log at `INFO` and above, with identifiers in fields.

## What breaks

1. **An error alert never fires.** Lines are plain text or use `level`, so they have no severity. Log JSON with `severity`, or match `jsonPayload.level`.
1. **Lines from one request are scattered.** No trace field. Add `logging.googleapis.com/trace` from the `X-Cloud-Trace-Context` header.
1. **The latency alert fires all day.** The service holds WebSockets or streams. Do not use a latency alert there.
1. **A 5xx alert stays quiet during an outage.** Requests refused at the maximum number of instances never reach `request_count`. Keep the uptime check, and read the request log.
1. **An alert fires once and floods the inbox.** A log match without `notificationRateLimit`. Set it.
1. **Alerts go to one person's inbox.** They leave or filter it. Use a group address, and a second channel.
1. **The log bill grows with traffic.** Your own access log duplicates Cloud Run's. Turn it off, then exclude or sample what you never read.
1. **Logs needed from two months ago are gone.** `_Default` keeps 30 days. Raise its retention with `gcloud logging buckets update _Default --location=global --retention-days=90`, at $0.01 per GiB-month past 30 days.

## A checklist

- Log one JSON object per line with `severity` and `message`; check your library's field names.
- Add the trace field, so that a request's lines are grouped.
- Create an email channel and send it a test.
- Add an uptime check on `/health` from three regions, and an alert on it.
- Add the 5xx threshold and the error log match, each with the first command to run in its documentation.
- Have all three in place before the switch, as [the cutover day checklist](https://exodus.elim.io/blog/the-cutover-day-checklist) asks.
- Look at Cloud Logging in the bill once a month; exclude only what you never read.

## Where Exodus comes in

Exodus does not install monitoring, and it does not sign in to your Google Cloud; your coding agent does that work, with your `gcloud`. What Exodus does after the move is `exodus bill`: it reads a month of your own bill from your billing export, read-only, grouped by service and SKU, so Cloud Logging and Cloud Monitoring appear next to Cloud Run, and with a linked account the cabinet sets the month against the report's estimate. The articles of this blog, this one included, are also what `exodus kb` and `exodus ask` read when your agent asks how to set up an alert.

## FAQ

### How long does Cloud Run keep logs?

30 days, in the _Default bucket that holds everything Cloud Run writes. Audit logs of administrative actions go to the _Required bucket and are kept 400 days at no charge. You can raise the retention of _Default; each GiB kept past 30 days costs $0.01 a month.

### Why do my Cloud Run logs have no severity?

Cloud Logging reads the level from a JSON field named severity. Plain text lines, and JSON that calls the field level, arrive with no severity, which the console shows as Default, and a filter on severity at ERROR or above misses them. Log one JSON object per line with severity and message.

### Are Cloud Run metrics free?

Yes. Cloud Run's own metrics, such as request count, latency, instance count, CPU and memory, need no setup and are not charged. Your own metrics, including log-based metrics, cost $0.2580 per MiB after the first 150 MiB per billing account each month.

### How fast does a Cloud Run alert arrive?

Two to seven minutes after a problem starts, for a metric alert. Most metrics become visible after about 60 seconds, policy computation adds up to 5 minutes 30 seconds, and the channel adds its own delay. Google warns that delivery to SMS and Slack is not guaranteed, so start with email.

### How do I lower the Cloud Run logging bill?

Turn off your own access log, because Cloud Run already writes one entry per request, then add an exclusion on the _Default sink for entries you never read, such as requests to the health path. Never exclude warnings or errors: log-based alerts do not see excluded entries.

## Sources

1. [Logging and viewing logs in Cloud Run, Google (request logs, container logs from stdout, stderr, /var/log, syslog and client libraries, system logs in varlog/system; integrated logging does not use entries.write quota; one line of JSON becomes jsonPayload, text becomes textPayload; severity and message special fields; logging.googleapis.com/trace from X-Cloud-Trace-Context nests container logs under the request log; request logs cannot be reduced from Cloud Run, use exclusions; gcloud run services logs read, gcloud beta run services logs tail in Preview with the log-streaming component; 'Starting new instance. Reason:' entries; updated Oct 9, 2026, read Oct 12, 2026)](https://docs.cloud.google.com/run/docs/logging)
2. [Monitor Cloud Run performance, Google (Cloud Run metrics need no setup and are not charged; key metrics for services; custom metrics through a sidecar or log-based metrics; uptime checks and alerts; updated Oct 9, 2026, read Oct 12, 2026)](https://docs.cloud.google.com/run/docs/monitoring)
3. [Google Cloud metrics P to Z, Cloud Monitoring (run.googleapis.com/request_count with response_code and response_code_class, excluding requests that do not reach an instance such as unauthorized ones or when maximum instances is reached; request_latencies from the container receiving the request to its exit, without startup latency; container/instance_count, cpu/utilizations, memory/utilizations, startup_latencies, billable_instance_time; sampled every 60 seconds, visible after up to 120 seconds; updated Oct 9, 2026, read Oct 12, 2026)](https://docs.cloud.google.com/monitoring/api/metrics_gcp_p_z)
4. [Google Cloud Observability pricing, Google (Logging $0.50/GiB with up to 30 days of storage, first 50 GiB per project per month free; retention past 30 days $0.01 per GiB per month; _Required bucket free, 400 days; _Default 30 days, configurable; Google Cloud metrics not chargeable; chargeable metrics $0.2580/MiB after 150 MiB per billing account, 8 bytes per scalar point; read API $0.50 per million time series after 1 million; uptime checks $0.30 per 1,000 executions after 1 million per project; alerting from no sooner than September 1, 2027: $0.35 a month per metric reference and $0.50 per million points returned, policies on uptime, billing and quota metrics not charged, log-match conditions return no points; Error Reporting no charge; Cloud Trace $0.20 per million spans after 2.5 million, Cloud Run spans not charged; read Oct 12, 2026)](https://cloud.google.com/products/observability/pricing)
5. [Pricing examples, Google Cloud Observability (30-day month of 86,400 execution periods of 30 seconds; one condition aggregated to one series per service returns one point per period; read Oct 12, 2026)](https://cloud.google.com/stackdriver/observability-pricing-examples)
6. [Configure log-based alerting policies, Cloud Logging, Google (one condition, combiner OR; conditionMatchedLog filter; notificationRateLimit period; autoClose default 7 days, minimum 30 minutes; log-based alerting policies do not operate on excluded logs and cannot count, use log-based metrics; gcloud monitoring policies create --policy-from-file; updated Oct 9, 2026, read Oct 12, 2026)](https://docs.cloud.google.com/logging/docs/alerting/log-based-alerts)
7. [Sample alerting policies in JSON, Cloud Monitoring, Google (conditionThreshold with aggregations, comparison, thresholdValue, duration and trigger; uptime check policy on the uptime_check/check_passed metric with ALIGN_NEXT_OLDER, REDUCE_COUNT_FALSE, 1200 s alignment and 600 s duration; error-ratio policy with ALIGN_DELTA and REDUCE_SUM; updated Oct 9, 2026, read Oct 12, 2026)](https://docs.cloud.google.com/monitoring/alerts/policies-in-json)
8. [Alerting behavior, Cloud Monitoring, Google (alignment period and retest window; most Google Cloud metrics not visible for 60 seconds, alert computation adds up to 5 minutes 30 seconds; SMS and Slack delivery not guaranteed; at most 1,000 open alerts per policy; updated Oct 9, 2026, read Oct 12, 2026)](https://docs.cloud.google.com/monitoring/alerts/concepts-indepth)
9. [Create and manage notification channels, Cloud Monitoring, Google (email, Mobile App, PagerDuty, SMS, Slack, webhooks, Pub/Sub, Google Chat; use email or Pub/Sub as a redundant channel; test a channel; updated Oct 9, 2026, read Oct 12, 2026)](https://docs.cloud.google.com/monitoring/support/notification-options)
10. [Create public uptime checks, Cloud Monitoring, Google (at least three checker regions; Cloud Run needs run.routes.invoke; gcloud monitoring uptime create with --resource-type=uptime-url; updated Oct 9, 2026, read Oct 12, 2026)](https://docs.cloud.google.com/monitoring/uptime-checks)
11. [gcloud monitoring uptime create, gcloud beta monitoring channels create, gcloud logging metrics create, gcloud logging sinks update, gcloud run services logs read (--help of gcloud 587.0.0: --period 1, 5, 10 or 15 minutes, default 1; --regions at least 3, default all; --timeout default 60; --service-agent-auth oidc-token; --add-exclusion; read Oct 12, 2026)](https://cloud.google.com/sdk/gcloud/reference/monitoring/uptime/create)
12. [Routing and storage overview, Cloud Logging, Google (_Required and _Default sinks; a sink has one inclusion filter and several exclusion filters; exclusions apply after the Logging API receives entries; updated Oct 9, 2026, read Oct 12, 2026)](https://docs.cloud.google.com/logging/docs/routing/overview)
13. [LogExclusion, Cloud Logging API reference, Google (an exclusion filter can use the sample function to exclude less than 100% of matching entries, example sample(insertId, 0.99); read Oct 12, 2026)](https://docs.cloud.google.com/logging/docs/reference/v2/rest/v2/exclusions)
14. [Logging query language, Google (sample(insertId, FRACTION) selects a deterministic share of entries; updated Oct 9, 2026, read Oct 12, 2026)](https://docs.cloud.google.com/logging/docs/view/logging-query-language)
15. [Log-based metrics overview and counter metrics, Cloud Logging, Google (user-defined log-based metrics are chargeable custom metrics; data only from entries received after the metric is created; counters written every minute; updated Oct 9, 2026, read Oct 12, 2026)](https://docs.cloud.google.com/logging/docs/logs-based-metrics)
16. [Cloud Logging quotas and limits, Google (a LogEntry is at most about 256 KiB; _Default and user-defined buckets 30 days by default; read Oct 12, 2026)](https://docs.cloud.google.com/logging/quotas)
17. [Configure the Logging agent, special fields in structured payloads, Google (a severity key fills LogEntry.severity, common severity strings are matched; message is the line shown in Logs Explorer; read Oct 12, 2026)](https://docs.cloud.google.com/logging/docs/agent/logging/configuration)
18. [Aggregate, analyze, and view errors, Cloud Run, Google (Error Reporting needs no setup; exceptions with a stack trace in stdout or stderr, Memory limit exceeded and No instances available errors; updated Oct 9, 2026, read Oct 12, 2026)](https://docs.cloud.google.com/run/docs/error-reporting)
19. [Error Reporting overview, Google (groups error events by cause; samples up to 1,000 errors an hour; updated Oct 9, 2026, read Oct 12, 2026)](https://docs.cloud.google.com/error-reporting/docs/grouping-errors)
20. [Cloud Run pricing, Google (2 million requests a month free under request-based billing; read Oct 12, 2026)](https://cloud.google.com/run/pricing)
21. Exodus team: log volume by log name and request count of the eight services in our own project over 30 days to 2026-10-12, severities of request logs and stdout lines, and our alerting policies, read-only (gcloud logging read, Monitoring API timeSeries.list, gcloud monitoring policies list), Oct 12, 2026
