feat: add privacy-safe server diagnostics

This commit is contained in:
inman committed 2026-08-30 16:01:42 +08:00
1 parent 2360506607
commit a3963ad0f6
27 files changed
+1305 -112

No files matched your search

+20 -6
View File
@@ -1,5 +1,6 @@
import pg from 'pg';
import type { AppConfig } from './config.js';
import { writeEmergencyDiagnostic } from './diagnostics.js';
const { Pool } = pg;
let pool: pg.Pool | null = null;
@@ -19,10 +20,17 @@ export function quoteIdentifier(identifier: string): string {
}
function logDatabaseError(context: string, error: unknown): void {
const value = error && typeof error === 'object' ? error as { code?: unknown; message?: unknown } : {};
const code = value.code ? ` (${String(value.code)})` : '';
const message = value.message ? String(value.message) : String(error);
console.error(`[database] ${context}${code}: ${message}`);
const event = context === 'idle pool client error'
? 'database.pool.idle_client_error'
: 'database.transaction.rollback_failed';
writeEmergencyDiagnostic(event, error, { diagnostic_stage: 'database' });
}
export class DatabaseStartupError extends Error {
constructor(public readonly code: string, message: string) {
super(message);
this.name = 'DatabaseStartupError';
}
}
export function getPool(config: AppConfig): pg.Pool {
@@ -106,9 +114,15 @@ export async function databaseReadiness(config: AppConfig): Promise<DatabaseRead
export async function assertDatabaseSchema(config: AppConfig): Promise<void> {
const readiness = await databaseReadiness(config);
if (!readiness.database) {
throw new Error(`数据库不可用,无法启动控制平面${readiness.errorCode ? `(${readiness.errorCode})` : ''}。`);
throw new DatabaseStartupError(
readiness.errorCode || 'database_unavailable',
`数据库不可用,无法启动控制平面${readiness.errorCode ? `(${readiness.errorCode})` : ''}。`
);
}
if (!readiness.schema) {
throw new Error(`数据库迁移 ${REQUIRED_SCHEMA_VERSION} 尚未应用,请先执行 npm run db:migrate。`);
throw new DatabaseStartupError(
'database_schema_outdated',
`数据库迁移 ${REQUIRED_SCHEMA_VERSION} 尚未应用,请先执行 npm run db:migrate。`
);
}
}