From 7b8e7751394e8578f08e93b553bb246b08dd539c Mon Sep 17 00:00:00 2001 From: MartinBraquet Date: Sun, 21 Sep 2025 14:55:32 +0200 Subject: [PATCH] Fix google cloud env --- backend/shared/src/firebase-utils.ts | 3 +- backend/shared/src/init-admin.ts | 32 +++++++++------- backend/shared/src/monitoring/log.ts | 4 +- .../shared/src/monitoring/metric-writer.ts | 38 ++++++++----------- common/src/envs/constants.ts | 8 +++- common/src/envs/prod.ts | 4 +- 6 files changed, 46 insertions(+), 43 deletions(-) diff --git a/backend/shared/src/firebase-utils.ts b/backend/shared/src/firebase-utils.ts index a453edc8..588996c8 100644 --- a/backend/shared/src/firebase-utils.ts +++ b/backend/shared/src/firebase-utils.ts @@ -3,7 +3,8 @@ import {ENV_CONFIG} from "common/envs/constants"; export const getServiceAccountCredentials = () => { let keyPath = ENV_CONFIG.googleApplicationCredentials - if (keyPath == null) { + // console.log('Using GOOGLE_APPLICATION_CREDENTIALS:', keyPath) + if (!keyPath) { throw new Error( `Please set the GOOGLE_APPLICATION_CREDENTIALS environment variable to contain the path to your key file.` ) diff --git a/backend/shared/src/init-admin.ts b/backend/shared/src/init-admin.ts index b5ef1d86..08031c68 100644 --- a/backend/shared/src/init-admin.ts +++ b/backend/shared/src/init-admin.ts @@ -2,22 +2,26 @@ import * as admin from 'firebase-admin' import {getServiceAccountCredentials} from "shared/firebase-utils"; +import {IS_LOCAL} from "common/envs/constants"; // Locally initialize Firebase Admin. export const initAdmin = () => { - try { - const serviceAccount = getServiceAccountCredentials() - console.log( - `Initializing connection to ${serviceAccount.project_id} Firebase...` - ) - return admin.initializeApp({ - projectId: serviceAccount.project_id, - credential: admin.credential.cert(serviceAccount), - storageBucket: `${serviceAccount.project_id}.appspot.com`, - }) - } catch (err) { - console.error(err) - console.log(`Initializing connection to default Firebase...`) - return admin.initializeApp() + if (IS_LOCAL) { + try { + const serviceAccount = getServiceAccountCredentials() + console.log( + `Initializing connection to ${serviceAccount.project_id} Firebase...` + ) + return admin.initializeApp({ + projectId: serviceAccount.project_id, + credential: admin.credential.cert(serviceAccount), + storageBucket: `${serviceAccount.project_id}.appspot.com`, + }) + } catch (err) { + console.error(err) + } } + + console.log(`Initializing connection to default Firebase...`) + return admin.initializeApp() } diff --git a/backend/shared/src/monitoring/log.ts b/backend/shared/src/monitoring/log.ts index f2851afd..2223683a 100644 --- a/backend/shared/src/monitoring/log.ts +++ b/backend/shared/src/monitoring/log.ts @@ -2,6 +2,7 @@ import { format } from 'node:util' import { isError, pick, omit } from 'lodash' import { dim, red, yellow } from 'colors/safe' import { getMonitoringContext } from './context' +import {IS_GOOGLE_CLOUD} from "common/envs/constants"; // mapping JS log levels (e.g. functions on console object) to GCP log levels const JS_TO_GCP_LEVELS = { @@ -13,7 +14,6 @@ const JS_TO_GCP_LEVELS = { const JS_LEVELS = Object.keys(JS_TO_GCP_LEVELS) as LogLevel[] const DEFAULT_LEVEL = 'info' -const IS_GCP = process.env.GOOGLE_CLOUD_PROJECT != null // keys to put in front to categorize a log line in the console const DISPLAY_CATEGORY_KEYS = ['endpoint', 'job'] as const @@ -72,7 +72,7 @@ function writeLog( const contextData = getMonitoringContext() const message = format(toString(msg), ...(rest ?? [])) const data = { ...(contextData ?? {}), ...(props ?? {}) } - if (IS_GCP) { + if (IS_GOOGLE_CLOUD) { const severity = JS_TO_GCP_LEVELS[level] const output: LogDetails = { severity, message, ...data } if (msg instanceof Error) { diff --git a/backend/shared/src/monitoring/metric-writer.ts b/backend/shared/src/monitoring/metric-writer.ts index 8f7d048f..30e640dd 100644 --- a/backend/shared/src/monitoring/metric-writer.ts +++ b/backend/shared/src/monitoring/metric-writer.ts @@ -1,25 +1,19 @@ -import { MetricServiceClient } from '@google-cloud/monitoring' -import { average, sumOfSquaredError } from 'common/util/math' -import { log } from './log' -import { InstanceInfo, getInstanceInfo } from './instance-info' -import { chunk } from 'lodash' -import { - CUSTOM_METRICS, - MetricStore, - MetricStoreEntry, - metrics, -} from './metrics' +import {MetricServiceClient} from '@google-cloud/monitoring' +import {average, sumOfSquaredError} from 'common/util/math' +import {log} from './log' +import {getInstanceInfo, InstanceInfo} from './instance-info' +import {chunk} from 'lodash' +import {CUSTOM_METRICS, metrics, MetricStore, MetricStoreEntry,} from './metrics' +import {IS_GOOGLE_CLOUD} from "common/envs/constants"; // how often metrics are written. GCP says don't write for a single time series // more than once per 5 seconds. export const METRICS_INTERVAL_MS = 60_000 -const LOCAL_DEV = process.env.GOOGLE_CLOUD_PROJECT == null - function serializeTimestamp(ts: number) { const seconds = ts / 1000 const nanos = (ts % 1000) * 1000 - return { seconds, nanos } as const + return {seconds, nanos} as const } // see https://cloud.google.com/monitoring/api/ref_v3/rest/v3/projects.snoozes#timeinterval @@ -31,7 +25,7 @@ function serializeInterval(entry: MetricStoreEntry, ts: number) { endTime: serializeTimestamp(ts), } case 'GAUGE': { - return { endTime: serializeTimestamp(ts) } + return {endTime: serializeTimestamp(ts)} } } } @@ -43,7 +37,7 @@ function serializeDistribution(points: number[]) { mean: average(points), sumOfSquaredDeviation: sumOfSquaredError(points), // not interested in handling histograms right now - bucketOptions: { explicitBuckets: { bounds: [0] } }, + bucketOptions: {explicitBuckets: {bounds: [0]}}, bucketCounts: [0, points.length], } } @@ -52,9 +46,9 @@ function serializeDistribution(points: number[]) { function serializeValue(entry: MetricStoreEntry) { switch (CUSTOM_METRICS[entry.type].valueKind) { case 'int64Value': - return { int64Value: entry.value } + return {int64Value: entry.value} case 'distributionValue': { - return { distributionValue: serializeDistribution(entry.points ?? []) } + return {distributionValue: serializeDistribution(entry.points ?? [])} } default: throw new Error('Other value kinds not yet implemented.') @@ -110,8 +104,8 @@ export class MetricWriter { for (const entry of freshEntries) { entry.fresh = false } - if (!LOCAL_DEV) { - log.debug('Writing GCP metrics.', { entries: freshEntries }) + if (!IS_GOOGLE_CLOUD) { + log.debug('Writing GCP metrics.', {entries: freshEntries}) if (this.instance == null) { this.instance = await getInstanceInfo() log.debug('Retrieved instance metadata.', { @@ -126,7 +120,7 @@ export class MetricWriter { for (const batch of chunk(timeSeries, 200)) { this.store.clearDistributionGauges() // see https://cloud.google.com/monitoring/custom-metrics/creating-metrics - await this.client.createTimeSeries({ timeSeries: batch, name }) + await this.client.createTimeSeries({timeSeries: batch, name}) } } } @@ -138,7 +132,7 @@ export class MetricWriter { try { await this.write() } catch (error) { - log.error('Failed to write metrics.', { error }) + log.error('Failed to write metrics.', {error}) } }, this.intervalMs) } diff --git a/common/src/envs/constants.ts b/common/src/envs/constants.ts index 7416925e..03bd8d85 100644 --- a/common/src/envs/constants.ts +++ b/common/src/envs/constants.ts @@ -17,8 +17,12 @@ export function isModId(id: string) { export const LOCAL_WEB_DOMAIN = 'localhost:3000'; export const LOCAL_BACKEND_DOMAIN = 'localhost:8088'; -export const IS_LOCAL = !process.env.VERCEL && !process.env.K_SERVICE; -console.log(IS_LOCAL ? 'Running in local mode' : 'Running in deployed mode', isProd() ? '(prod)' : '(dev)'); + +export const IS_GOOGLE_CLOUD = !!process.env.GOOGLE_CLOUD_PROJECT +export const IS_VERCEL = !!process.env.VERCEL +export const IS_LOCAL = !IS_GOOGLE_CLOUD && !IS_VERCEL +export const HOSTING_ENV = IS_GOOGLE_CLOUD ? 'Google Cloud' : IS_VERCEL ? 'Vercel' : IS_LOCAL ? 'local' : 'unknown' +console.log(`Running in ${HOSTING_ENV}`, isProd() ? '(prod)' : '(dev)'); export const DOMAIN = IS_LOCAL ? LOCAL_WEB_DOMAIN : ENV_CONFIG.domain export const BACKEND_DOMAIN = IS_LOCAL ? LOCAL_BACKEND_DOMAIN : ENV_CONFIG.backendDomain diff --git a/common/src/envs/prod.ts b/common/src/envs/prod.ts index 7d36586d..b65a05ce 100644 --- a/common/src/envs/prod.ts +++ b/common/src/envs/prod.ts @@ -6,7 +6,7 @@ export type EnvConfig = { supabasePwd?: string posthogKey: string backendDomain: string - googleApplicationCredentials: string + googleApplicationCredentials: string | undefined // IDs for v2 cloud functions -- find these by deploying a cloud function and // examining the URL, https://[name]-[cloudRunId]-[cloudRunRegion].a.run.app @@ -38,7 +38,7 @@ export const PROD_CONFIG: EnvConfig = { supabaseInstanceId: 'ltzepxnhhnrnvovqblfr', supabaseAnonKey: process.env.NEXT_PUBLIC_SUPABASE_KEY || '', supabasePwd: process.env.SUPABASE_DB_PASSWORD || '', - googleApplicationCredentials: process.env.GOOGLE_APPLICATION_CREDENTIALS || '', + googleApplicationCredentials: process.env.GOOGLE_APPLICATION_CREDENTIALS, firebaseConfig: { apiKey: process.env.NEXT_PUBLIC_FIREBASE_API_KEY || '', authDomain: "compass-130ba.firebaseapp.com",