diff --git a/.github/workflows/deploy-cloud-run-production.yml b/.github/workflows/deploy-cloud-run-production.yml index ce518e7ea..050239aaf 100644 --- a/.github/workflows/deploy-cloud-run-production.yml +++ b/.github/workflows/deploy-cloud-run-production.yml @@ -121,7 +121,8 @@ jobs: --set-env-vars "API_KEY_SECRET=${{ secrets.API_KEY_SECRET_PRODUCTION }}" \ --set-env-vars "SENTRY_DSN=${{ secrets.SENTRY_DSN_PRODUCTION }}" \ --set-env-vars "ADMIN_API_KEY=${{ secrets.ADMIN_API_KEY_PRODUCTION }}" \ - --set-env-vars "POSTHOG_API_KEY=${{ secrets.POSTHOG_API_KEY_PRODUCTION }}" \ + --set-env-vars "POSTHOG_PROJECT_TOKEN=${{ secrets.POSTHOG_PROJECT_TOKEN }}" \ + --set-env-vars "POSTHOG_HOST=https://us.i.posthog.com" \ --memory 1Gi \ --cpu 2 \ --min-instances 2 \ diff --git a/.github/workflows/deploy-cloud-run-staging.yml b/.github/workflows/deploy-cloud-run-staging.yml index a52d5db22..15fbdb96f 100644 --- a/.github/workflows/deploy-cloud-run-staging.yml +++ b/.github/workflows/deploy-cloud-run-staging.yml @@ -119,7 +119,8 @@ jobs: --set-env-vars "REDIS_URL=${{ secrets.REDIS_STAGING_URL }}" \ --set-env-vars "API_KEY_SECRET=${{ secrets.API_KEY_SECRET_STAGING }}" \ --set-env-vars "SENTRY_DSN=${{ secrets.SENTRY_DSN_STAGING }}" \ - --set-env-vars "POSTHOG_API_KEY=${{ secrets.POSTHOG_API_KEY_PRODUCTION }}" \ + --set-env-vars "POSTHOG_PROJECT_TOKEN=${{ secrets.POSTHOG_PROJECT_TOKEN }}" \ + --set-env-vars "POSTHOG_HOST=https://us.i.posthog.com" \ --port 8000 \ --memory 1Gi \ --cpu 2 \ diff --git a/.github/workflows/fix-secret-manager-iam.yml b/.github/workflows/fix-secret-manager-iam.yml index cd08faf71..cb6061334 100644 --- a/.github/workflows/fix-secret-manager-iam.yml +++ b/.github/workflows/fix-secret-manager-iam.yml @@ -31,7 +31,7 @@ jobs: --role="roles/secretmanager.secretAccessor" \ --project=gaia-calendar-488606 \ 2>/dev/null || echo "Secret may not exist yet, will be created during deploy" - gcloud secrets add-iam-policy-binding buywhere-posthog-api-key \ + gcloud secrets add-iam-policy-binding buywhere-posthog-project-token \ --member="serviceAccount:${{ env.CLOUD_RUN_SA }}" \ --role="roles/secretmanager.secretAccessor" \ --project=gaia-calendar-488606 \ diff --git a/api/src/analytics/posthog.ts b/api/src/analytics/posthog.ts index 6705dd3be..a7dc37482 100644 --- a/api/src/analytics/posthog.ts +++ b/api/src/analytics/posthog.ts @@ -1,18 +1,37 @@ import { PostHog } from 'posthog-node'; -const POSTHOG_API_KEY = process.env.POSTHOG_API_KEY || ''; -const POSTHOG_HOST = process.env.POSTHOG_HOST || 'https://app.posthog.com'; +const POSTHOG_PROJECT_TOKEN = process.env.POSTHOG_PROJECT_TOKEN || ''; +const POSTHOG_HOST = process.env.POSTHOG_HOST || 'https://us.i.posthog.com'; let client: PostHog | null = null; function getClient(): PostHog | null { - if (!POSTHOG_API_KEY) return null; + if (!POSTHOG_PROJECT_TOKEN) return null; if (!client) { - client = new PostHog(POSTHOG_API_KEY, { host: POSTHOG_HOST }); + client = new PostHog(POSTHOG_PROJECT_TOKEN, { host: POSTHOG_HOST }); } return client; } +export async function getFeatureFlag(key: string, distinctId: string): Promise { + const ph = getClient(); + if (!ph) return undefined; + return ph.getFeatureFlag(key, distinctId); +} + +export async function isFeatureEnabled(key: string, distinctId: string): Promise { + const ph = getClient(); + if (!ph) return false; + const result = await ph.isFeatureEnabled(key, distinctId); + return result ?? false; +} + +export function captureException(error: unknown, distinctId?: string, additionalProperties?: Record): void { + const ph = getClient(); + if (!ph) return; + ph.captureException(error, distinctId, additionalProperties); +} + export interface ApiQueryEvent { apiKey: string; agentFramework: string; diff --git a/api/src/server.ts b/api/src/server.ts index f3285a3a5..d44fe2d00 100644 --- a/api/src/server.ts +++ b/api/src/server.ts @@ -1,6 +1,7 @@ import express from 'express'; import cors from 'cors'; import { Sentry, sentryRequestHandler } from './sentry'; +import { captureException as posthogCaptureException } from './analytics/posthog'; import authRouter from './routes/auth'; import productsRouter from './routes/products'; import categoriesRouter from './routes/categories'; @@ -188,6 +189,7 @@ export function createApp() { // eslint-disable-next-line @typescript-eslint/no-unused-vars app.use((err: Error, _req: express.Request, res: express.Response, next: express.NextFunction) => { Sentry.captureException(err); + posthogCaptureException(err); next(err); }); diff --git a/deploy/gcp/api-service.yaml b/deploy/gcp/api-service.yaml index 678a7a1c1..47e8a36da 100644 --- a/deploy/gcp/api-service.yaml +++ b/deploy/gcp/api-service.yaml @@ -48,11 +48,13 @@ spec: secretKeyRef: name: buywhere-admin-api-key key: latest - - name: POSTHOG_API_KEY + - name: POSTHOG_PROJECT_TOKEN valueFrom: secretKeyRef: - name: buywhere-posthog-api-key + name: buywhere-posthog-project-token key: latest + - name: POSTHOG_HOST + value: "https://us.i.posthog.com" resources: limits: cpu: "1"