Fix google cloud env

This commit is contained in:
MartinBraquet
2025-09-21 14:55:32 +02:00
parent 86a7d26bfd
commit 7b8e775139
6 changed files with 46 additions and 43 deletions

View File

@@ -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.`
)

View File

@@ -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()
}

View File

@@ -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) {

View File

@@ -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)
}

View File

@@ -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

View File

@@ -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",