mirror of
https://github.com/simstudioai/sim.git
synced 2026-09-24 15:45:35 +08:00
feat(db): attribute Postgres connections by runtime via application_name (#5211)
* feat(db): attribute Postgres connections by runtime via application_name * improvement(db): label migration-runner connection sim-migrate; trim DB_APP_NAME comment * fix(db): label realtime's shared @sim/db connections sim-realtime too The realtime process uses both its own socketDb pool and the shared @sim/db client (handlers, preflight, permissions). Only socketDb was labeled, so the shared client defaulted to sim-app, mislabeling much of realtime's DB traffic. Set DB_APP_NAME=sim-realtime at the process level (bootstrap before the dynamic @/index import for prod; dev/start scripts for local) so both clients report it.
This commit is contained in:
@@ -9,8 +9,8 @@
|
||||
"node": ">=20.0.0"
|
||||
},
|
||||
"scripts": {
|
||||
"dev": "bun --watch src/index.ts",
|
||||
"start": "bun src/index.ts",
|
||||
"dev": "DB_APP_NAME=sim-realtime bun --watch src/index.ts",
|
||||
"start": "DB_APP_NAME=sim-realtime bun src/index.ts",
|
||||
"type-check": "tsc --noEmit",
|
||||
"lint": "biome check --write --unsafe .",
|
||||
"lint:check": "biome check .",
|
||||
|
||||
@@ -6,4 +6,11 @@
|
||||
import { loadRuntimeSecrets } from '@sim/runtime-secrets'
|
||||
|
||||
await loadRuntimeSecrets()
|
||||
/**
|
||||
* Label every Postgres connection this process opens as `sim-realtime` — both
|
||||
* the realtime `socketDb` pool and the shared `@sim/db` client used by handlers,
|
||||
* preflight, and permissions. Set before importing `@/index` so it lands before
|
||||
* `@sim/db` reads it at module-eval time. `??=` respects an explicit override.
|
||||
*/
|
||||
process.env.DB_APP_NAME ??= 'sim-realtime'
|
||||
await import('@/index')
|
||||
|
||||
@@ -40,6 +40,7 @@ const socketDb = drizzle(
|
||||
connect_timeout: 20,
|
||||
max: 15,
|
||||
onnotice: () => {},
|
||||
connection: { application_name: process.env.DB_APP_NAME ?? 'sim-realtime' },
|
||||
}),
|
||||
'socketDb'
|
||||
),
|
||||
|
||||
@@ -20,6 +20,7 @@ export const env = createEnv({
|
||||
// Core Database & Authentication
|
||||
DATABASE_URL: z.string().url(), // Primary database connection string
|
||||
DATABASE_REPLICA_URL: z.string().url().optional(), // Read-replica connection string; opt-in reads fall back to the primary when unset
|
||||
DB_APP_NAME: z.string().optional(), // Postgres application_name for query attribution (sim-app/sim-trigger/sim-realtime)
|
||||
BETTER_AUTH_URL: z.string().url(), // Base URL for Better Auth service
|
||||
BETTER_AUTH_SECRET: z.string().min(32), // Secret key for Better Auth JWT signing
|
||||
DISABLE_REGISTRATION: z.boolean().optional(), // Flag to disable new user registration
|
||||
|
||||
@@ -2,7 +2,11 @@ import { OTLPLogExporter } from '@opentelemetry/exporter-logs-otlp-http'
|
||||
import { OTLPMetricExporter } from '@opentelemetry/exporter-metrics-otlp-http'
|
||||
import { OTLPTraceExporter } from '@opentelemetry/exporter-trace-otlp-http'
|
||||
import { resourceFromAttributes } from '@opentelemetry/resources'
|
||||
import { additionalFiles, additionalPackages } from '@trigger.dev/build/extensions/core'
|
||||
import {
|
||||
additionalFiles,
|
||||
additionalPackages,
|
||||
syncEnvVars,
|
||||
} from '@trigger.dev/build/extensions/core'
|
||||
import { defineConfig } from '@trigger.dev/sdk'
|
||||
import { env } from './lib/core/config/env'
|
||||
import { parseOtlpHeaders } from './lib/monitoring/otlp'
|
||||
@@ -58,6 +62,7 @@ export default defineConfig({
|
||||
build: {
|
||||
external: ['isolated-vm', '@earendil-works/pi-coding-agent', 'cpu-features'],
|
||||
extensions: [
|
||||
syncEnvVars(() => [{ name: 'DB_APP_NAME', value: 'sim-trigger' }]),
|
||||
additionalFiles({
|
||||
files: [
|
||||
'./lib/execution/isolated-vm-worker.cjs',
|
||||
|
||||
@@ -13,6 +13,7 @@ const poolOptions = {
|
||||
idle_timeout: 20,
|
||||
connect_timeout: 30,
|
||||
onnotice: () => {},
|
||||
connection: { application_name: process.env.DB_APP_NAME ?? 'sim-app' },
|
||||
}
|
||||
|
||||
const postgresClient = instrumentPoolClient(
|
||||
|
||||
@@ -45,7 +45,12 @@ const hasDirectMigrationUrl = Boolean(process.env.MIGRATION_DATABASE_URL)
|
||||
* default recycles the connection after 30–60 min, silently dropping the
|
||||
* session advisory lock and `SET`s.
|
||||
*/
|
||||
const client = postgres(url, { max: 1, connect_timeout: 10, max_lifetime: null })
|
||||
const client = postgres(url, {
|
||||
max: 1,
|
||||
connect_timeout: 10,
|
||||
max_lifetime: null,
|
||||
connection: { application_name: 'sim-migrate' },
|
||||
})
|
||||
|
||||
/**
|
||||
* Cross-process migration lock. drizzle's `migrate()` has no built-in lock, so
|
||||
|
||||
Reference in New Issue
Block a user