Skip to content

Add GCP telemetry integration#238

Open
arseniycodes wants to merge 7 commits into
mainfrom
ash/gcp-integration
Open

Add GCP telemetry integration#238
arseniycodes wants to merge 7 commits into
mainfrom
ash/gcp-integration

Conversation

@arseniycodes

@arseniycodes arseniycodes commented Jul 14, 2026

Copy link
Copy Markdown
Contributor

Summary

  • add an OAuth-based GCP project connection flow that provisions an integration-owned Pub/Sub topic, subscription, and Cloud Logging sink without retaining the customer's OAuth token
  • authenticate Cloud Logging push delivery and translate log entries into tenant-scoped OTLP logs
  • pull a curated set of Cloud Monitoring metrics through keyless workload identity, with an atomic monthly cap of 100 million returned series per connection
  • expose connection status and callback outcomes in Settings, and add the generated 0098 database migration for GCP connection state

Cost behavior

Pub/Sub and Monitoring API quota are billed to the integration project. The persisted monthly reservation prevents concurrent workers from starting metric reads beyond the configured cap.

Validation

  • API GCP, ingest-filter, and capability tests
  • proxy Pub/Sub authentication and source-filter tests
  • worker metric-budget, puller, and Monitoring client tests
  • web callback-model tests
  • API, proxy, worker, web, and database typechecks
  • full migration-ledger test
  • seeded worktree verification through the proxy and collector

Summary by cubic

Add Google Cloud telemetry integration: connect a GCP project via OAuth, stream logs via authenticated Pub/Sub push, and pull curated Cloud Monitoring metrics under a monthly cap. Adds Settings UI, hardened provisioning and safe replacement, and fixes cleanup provenance and metric checkpoints. Creates a new gcp_connections table.

  • New Features

    • OAuth connect flow that creates an integration-owned Pub/Sub topic/subscription and a customer Cloud Logging sink; no customer token is stored.
    • Proxy intake for Pub/Sub push that verifies Google ID tokens (service account + audience) and translates Cloud Logging entries to tenant-scoped OTLP logs.
    • Worker pulls curated Cloud Monitoring metrics via Application Default Credentials using @superlog/gcp-auth, enforces a per-connection monthly returned-series cap (default 100M), and improves metric conversion (typed values and distributions); quota is billed to the integration project.
    • Per-connection ingest key is minted and stored encrypted for forwarding pulled metrics; proxy exposes /gcp/pull/metrics.
    • Settings: start/connect callback, connection status, and last received timestamps; ingest filters now include gcp logs/metrics.
    • Capability gate gcpConnect enabled only when required env vars are set.
    • Hardened connection lifecycle: idempotent create, reuse of existing active connections, safer reconnect and safe replacement; fixed cleanup provenance and metrics cursor checkpointing to avoid re-reads.
  • Migration

    • Run DB migrations 0104 and 0105 to create and extend gcp_connections.
    • Configure env:
      • API: GCP_OAUTH_CLIENT_ID, GCP_OAUTH_CLIENT_SECRET, GCP_OAUTH_REDIRECT_URI, GCP_INTEGRATION_PROJECT_ID, GCP_READER_SERVICE_ACCOUNT_EMAIL, GCP_PUBSUB_PUSH_SERVICE_ACCOUNT_EMAIL, GCP_PUBSUB_PUSH_ENDPOINT, GCP_PUBSUB_PUSH_AUDIENCE, GCP_WORKLOAD_IDENTITY_CONFIG (when not on GCP).
      • Proxy: GCP_PUBSUB_PUSH_SERVICE_ACCOUNT_EMAIL, GCP_PUBSUB_PUSH_AUDIENCE.
      • Worker: GCP_INTEGRATION_PROJECT_ID, GCP_METRICS_INTAKE_URL, GCP_METRICS_MONTHLY_SERIES_LIMIT (optional), GCP_WORKLOAD_IDENTITY_CONFIG (when not on GCP).
    • Ensure Application Default Credentials are available (e.g., workload identity) for API/proxy/worker; do not use downloaded keys.
    • Align the Pub/Sub push subscription’s OIDC service account and audience with the proxy settings and expose the proxy push URL.
    • New dependencies: google-auth-library added to api, proxy, and worker; new workspace package @superlog/gcp-auth used by api and worker.

Written for commit f07724e. Summary will update on new commits.

Review in cubic

@arseniycodes arseniycodes force-pushed the ash/gcp-integration branch from 908b821 to 9523789 Compare July 14, 2026 10:40

@cubic-dev-ai cubic-dev-ai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Review completed against the latest diff

Heads up: you’re close to your included review allowance. Set a flex budget so reviews don’t pause.

Re-trigger cubic

Comment thread apps/api/src/gcp/application.ts Outdated
Comment thread apps/api/src/system-capabilities.ts
Comment thread apps/api/src/system-capabilities.ts
Comment thread apps/worker/src/gcp/metrics-puller.ts
Comment thread apps/proxy/src/index.ts Outdated
Comment thread packages/db/migrations/0098_lonely_dreadnoughts.sql Outdated
Comment thread apps/api/src/gcp/repository.ts
Comment thread apps/api/src/gcp/interfaces.ts Outdated
Comment thread apps/api/src/gcp/interfaces.ts
Comment thread apps/api/src/gcp/gcp.test.ts
@arseniycodes arseniycodes force-pushed the ash/gcp-integration branch from 9523789 to ef659cc Compare July 14, 2026 17:41
@arseniycodes

Copy link
Copy Markdown
Contributor Author

@cubic-dev-ai review this PR against the latest head, including the fixes for the prior findings.

@cubic-dev-ai

cubic-dev-ai Bot commented Jul 14, 2026

Copy link
Copy Markdown
Contributor

@cubic-dev-ai review this PR against the latest head, including the fixes for the prior findings.

@arseniycodes I can't start this review because your workspace has reached its monthly review limit. cubic has reviewed 81,271 of the 80,000 allowed lines of code this month. Reviews resume on 3 August 2026 (in 20 days). Enable flex capacity to cover overages automatically and resume reviews now. Learn how flex capacity works.

To help optimise your usage, you can tune cubic to get the most out of your usage limits:

Learn more →

@arseniycodes

Copy link
Copy Markdown
Contributor Author

@codex review pls

@arseniycodes arseniycodes force-pushed the ash/gcp-integration branch from ef659cc to 315ce3c Compare July 14, 2026 18:05

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: ef659ccb4c

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread apps/proxy/src/index.ts
Comment thread apps/api/src/gcp/repository.ts Outdated
Comment thread apps/api/src/gcp/google-gateway.ts Outdated
Comment thread apps/api/src/gcp/repository.ts Outdated
@arseniycodes

Copy link
Copy Markdown
Contributor Author

@codex review

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: de8c23c25c

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread apps/api/src/gcp/repository.ts
Comment thread apps/worker/src/gcp/metrics-puller.ts
@arseniycodes

Copy link
Copy Markdown
Contributor Author

@codex review

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 783f79393e

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread apps/api/src/gcp/google-gateway.ts
Comment thread apps/api/src/gcp/application.ts Outdated
Comment thread apps/worker/src/gcp/metrics-puller.ts Outdated
@arseniycodes

Copy link
Copy Markdown
Contributor Author

@codex review

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: f07724eda4

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment on lines +109 to +113
eq(schema.gcpConnections.projectId, row.projectId),
ne(schema.gcpConnections.id, row.id),
eq(schema.gcpConnections.status, "connected"),
isNull(schema.gcpConnections.revokedAt),
),

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Only revoke the connection that was cleaned up

When two OAuth callbacks for different new GCP connections on the same Superlog project overlap, each request only deprovisions the superseded row it observed before provisioning, but this transaction revokes every other connected row at commit time. If callback B commits after callback A, B marks A revoked without ever calling gateway.deprovision for A's sink/topic/subscription, leaving live Google resources with no active DB row. Restrict this update to the specific superseded connection that was actually cleaned up, or serialize connection completion per project.

Useful? React with 👍 / 👎.

Comment on lines +423 to +424
body: JSON.stringify({
policy: removeMember(projectPolicy, "roles/monitoring.viewer", readerMember),

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Preserve monitoring grants used by other connections

If the same customer GCP project is connected to another Superlog project, that later connection will see the shared reader service account already present and store monitoringViewerGrantCreated=false. When this older connection is replaced or cleaned up, this branch still removes the shared roles/monitoring.viewer member from the customer project, so the other active connection's metrics pulls start failing even though its DB row remains connected. Check for other non-revoked connections to the same gcpProjectId before removing the IAM member, or make the grant ownership per connection.

Useful? React with 👍 / 👎.

.object({
otlp: z.object({ traces: z.boolean(), logs: z.boolean(), metrics: z.boolean() }).strict(),
aws: z.object({ logs: z.boolean(), metrics: z.boolean() }).strict(),
gcp: z.object({ logs: z.boolean(), metrics: z.boolean() }).strict(),

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Default GCP ingest filters for older clients

During a rolling deploy or for users with a cached pre-GCP web bundle, the ingest-filter PUT still sends the full previous state without a gcp key. Because this schema is strict and now requires gcp, those otherwise valid saves return 400 and no filter changes are persisted until the client reloads. Treat a missing gcp section as enabled-by-default to keep existing clients compatible with the new source.

Useful? React with 👍 / 👎.

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.

1 participant