Skip to content

test: e2e verification of built-in metrics and fail-open behavior; panic guard on the record path - #1186

Merged
panavenue merged 2 commits into
feature/client-side-metricsfrom
metrics-e2e
Oct 21, 2026
Merged

panavenue merged 2 commits into
feature/client-side-metricsfrom
metrics-e2e

Conversation

@panavenue

Copy link
Copy Markdown
Collaborator

Summary

Automates what we have been verifying by hand with the cmd/metric_prototype branch (#1139), and adds a last-line-of-defence guard so metrics can never break connectivity.

Stacked on #1185. Only the last commit is new; GitHub will retarget to feature/client-side-metrics once #1185 merges.

E2E tests (e2e_metrics_test.go, run by the existing integration-test job)

Test What it proves Against
TestMetricsE2EExport After one real dial + Close(), all five metrics arrive in Cloud Monitoring for this process's client_uid, with the documented labels (application_name, database_engine_type=postgresql, connector_type=go, region, resource_id, resolved instance_ip_type, valid compute_platform, status=success). real instance + real Monitoring API
TestMetricsE2EFailOpenUnreachableEndpoint With the Monitoring endpoint unroutable (real DeadlineExceeded/Unavailable): dials succeed, dial p50 matches a metrics-off dialer, Close() returns within the shutdown timeout, nothing on the standard logger (transient tier). real instance, unroutable metrics endpoint
TestMetricsE2EFailOpenBadCredentials With an invalid token (real Unauthenticated): dials succeed, exactly one standard-logger warning with role/project/opt-out hint, export suspended (1–3 attempts in the window). real instance + real Monitoring API

All three pass locally against jinphou-playground:us-west1:pg-dev (export verified in ~13 s). They skip under -short like the other e2e tests and only need POSTGRES_CONNECTION_NAME.

One-time CI setup needed

The e2e identities on cloud-sql-connector-testing (cloud-build-pool@… and the compute default SA) currently have cloudsql.client but no Monitoring roles, so TestMetricsE2EExport will skip in CI (with the exact gcloud commands in the skip message) until these are granted:

gcloud projects add-iam-policy-binding cloud-sql-connector-testing --member=serviceAccount:<e2e SA> --role=roles/monitoring.metricWriter
gcloud projects add-iam-policy-binding cloud-sql-connector-testing --member=serviceAccount:<e2e SA> --role=roles/monitoring.viewer

The two fail-open tests need no IAM and run everywhere.

Panic guard

Every MetricRecorder.Record* method now defers recover(). The OTel SDK does not panic in practice, but with metrics on by default in every connector and proxy process, "unlikely" should be "impossible" on the dial path. TestRecordNeverPanics uses a recorder with nil instruments and fails if the guard is removed (verified).

Plumbing

  • internal/tel/export_test.go → internal/tel/testhooks.go (non-_test, so the external e2e package can use the hooks; internal/ is not importable outside the module).
  • New root export_test.go exposing WithMetricClientOptionsForTest, DialerIDForTest, DetectPrincipalForTest, MetricShutdownTimeoutForTest to cloudsqlconn_test.

Follow-ups

  • Grant the two Monitoring roles to the e2e SA(s) so the export test is live in CI.
  • The connectors/tools prober (G2) can reuse TestMetricsE2EExport's body against the released connector/proxy, plus an absence alert on open_connection_count for the prober's client_uid.
  • Close feat: add cmd/metric_prototype/ folder for testing system metric #1139 (prototype) once this merges.

@panavenue
panavenue requested a review from a team as a code owner October 21, 2026 15:15
Base automatically changed from metrics-quiet-export to feature/client-side-metrics October 21, 2026 16:30
…nic guard on the record path

Replaces the manual prototype (cmd/metric_prototype) with automated
coverage that runs in the existing integration-test job:

- TestMetricsE2EExport: dial the e2e instance with metrics enabled and a
  unique application_name, Close (flush), then poll Cloud Monitoring for
  this process's client_uid and assert all five metrics arrive with the
  documented label values. Skips with the exact gcloud commands when the
  e2e identity lacks roles/monitoring.metricWriter or monitoring.viewer.
- TestMetricsE2EFailOpenUnreachableEndpoint: metrics pointed at an
  unroutable endpoint (real DeadlineExceeded/Unavailable). Dials succeed,
  dial p50 matches a metrics-off dialer, Close returns within the
  shutdown timeout, nothing on the standard logger.
- TestMetricsE2EFailOpenBadCredentials: an invalid token yields a real
  Unauthenticated. Dials succeed, exactly one standard-logger warning
  with remediation, export suspended (1-3 attempts in the window).

All three pass against a real instance and the real Monitoring API; they
skip under -short like the other e2e tests.

Also add a deferred recover() to every MetricRecorder.Record* method so a
panic inside the metrics SDK can never reach the dial path, with a test
that fails when the guard is removed. Test hooks move from
internal/tel/export_test.go to testhooks.go so the external e2e package
can use them; export_test.go in the root package exposes the few
unexported accessors the e2e tests need.
Comment thread internal/tel/tel.go Outdated
Comment thread e2e_metrics_test.go
…2e test

Review feedback on #1186. A bare recover() would make a bug in the
metrics pipeline invisible. recoverPanic now counts recovered panics in
tel.RecoveredPanics, debug-logs once per recorder, and writes one line
per process to the standard logger with a link to file an issue. The
dial path is still never affected. The e2e bad-credentials test uses
atomic.Int32 instead of a mutex for its call counter.
@panavenue
panavenue merged commit 6b30d3d into feature/client-side-metrics Oct 21, 2026
14 checks passed
@panavenue
panavenue deleted the metrics-e2e branch October 21, 2026 18:10
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants