Home
On-call

Google Cloud Monitoring

Send Cloud Monitoring alerts to a BatonDeck board. An alert that opens files an incident ticket; the same alert closing annotates that ticket rather than filing a second one.

Send Cloud Monitoring alerts to a BatonDeck board. An alert that opens files an incident ticket; the same alert closing annotates that ticket rather than filing a second one.

What Cloud Monitoring can and cannot send

This is the part that trips people up, so it is first.

Custom headersNo. Webhook channels do not support them.
SigningNo. Cloud Monitoring cannot compute a signature.
HTTP Basic authYes — this is what you use.
Query-string tokenSupported by Google, not accepted by us.

We do not accept the query-string token because a credential in a URL ends up in access logs, proxy logs and referrer headers. Basic auth puts it in a header instead, which is why that is the only mode this source offers.

1. Create the integration

From the web app: On-call → gear → New → Google Cloud Monitoring. The browser generates the key and shows it once — copy it then, it cannot be retrieved afterwards.

Or over MCP:

create_integration {
  projectId, name: "gcp-prod", source: "gcp", boardId: "B-…",
  auth: { mode: "basic", apiKey: "<a long random value you generate>" },
  routing: { mode: "oncall", onCallAgent: "claude-oncall" }
}

The response carries endpointPath/i/ing_…. Your full URL is the on-call function's base URL followed by that path.

2. Create the notification channel

In Cloud Console: Monitoring → Alerting → Edit notification channels → Webhooks → Add new.

  • Endpoint URLhttps://<function-host>/i/ing_…
  • Authentication — choose Basic auth
  • Username — anything (batondeck is fine; it is ignored)
  • Password — the key from step 1

Or with gcloud:

gcloud beta monitoring channels create \
  --display-name="BatonDeck on-call" \
  --type=webhook_basicauth \
  --channel-labels=url=https://<function-host>/i/ing_… \
  --user-labels=owner=batondeck

The username is ignored on purpose. The password is the whole secret, and pinning a username would add a second thing to get wrong for no security gain.

3. Attach it to an alerting policy

Any policy will do. Add the channel under Notifications, and turn on Notify on incident closure so the resolve reaches us — without it the ticket never learns the alert recovered.

gcloud alpha monitoring policies update POLICY_ID \
  --add-notification-channels=projects/PROJECT/notificationChannels/CHANNEL_ID

What lands on the ticket

Alert fieldWhere it goes
incident.incident_idthe correlation fingerprint
incident.stateopen → firing, closed → resolved
incident.policy_nameticket title — your own name for the alert (falls back to condition name, then summary)
incident.summarykept as an annotation; Google auto-generates it and it reads identically for every incident on a policy
incident.urla link on the ticket
incident.severityticket priority (defaults to warning when absent)
resource.*, metric.*, policy_user_labelslabels, prefixed resource. / metric. / user.
threshold_value, observed_value, documentationannotations

Correlation is automatic. Cloud Monitoring reuses one incident_id for the open and the close, so the close finds the ticket the open created with nothing to configure. A flapping alert appends to the same ticket instead of filing dozens.

Checking it works

Send a test from the integration's page (Send test event) — that proves the board path but not your credential, because a test event is synthesized inside BatonDeck and skips signature verification entirely. To prove the credential, fire a real alert (a policy on a metric you can move) and watch the delivery log.

If deliveries are refused:

Delivery log saysCause
basic_missingthe channel is not using Basic auth, or is sending nothing
basic_malformedthe header is not Basic base64(user:pass)
api_key_mismatchthe password does not match the key you created

A 404 for the whole endpoint means the integration id in the URL is wrong or the integration was disabled — the two are deliberately indistinguishable from outside.