diff --git a/packages/backend/src/GlobalModule.ts b/packages/backend/src/GlobalModule.ts index a2c834a740..55cf77ea83 100644 --- a/packages/backend/src/GlobalModule.ts +++ b/packages/backend/src/GlobalModule.ts @@ -31,16 +31,17 @@ const $config: Provider = { const $db: Provider = { provide: DI.db, - useFactory: async (config) => { + useFactory: async (config: Config, loggerService: LoggerService) => { + const dbLogger = loggerService.getLogger('db'); try { - const db = createPostgresDataSource(config); + const db = createPostgresDataSource(config, dbLogger); return await db.initialize(); } catch (e) { - console.error('failed to initialize database connection', e); + dbLogger.error('failed to initialize database connection', { e }); throw e; } }, - inject: [DI.config], + inject: [DI.config, LoggerService], }; const $meilisearch: Provider = { diff --git a/packages/backend/src/postgres.ts b/packages/backend/src/postgres.ts index 45caec54ce..01f5f0d19c 100644 --- a/packages/backend/src/postgres.ts +++ b/packages/backend/src/postgres.ts @@ -9,7 +9,7 @@ import { DataSource, Logger, type QueryRunner } from 'typeorm'; import * as highlight from 'cli-highlight'; import { entities as charts } from '@/core/chart/entities.js'; import { Config } from '@/config.js'; -import MisskeyLogger from '@/logger.js'; +import MisskeyLogger, { type Data } from '@/logger.js'; import { bindThis } from '@/decorators.js'; import { MiAbuseUserReport } from '@/models/AbuseUserReport.js'; @@ -95,12 +95,6 @@ import { SkApInboxLog } from '@/models/SkApInboxLog.js'; pg.types.setTypeParser(20, Number); -export const dbLogger = new MisskeyLogger('db'); - -const sqlLogger = dbLogger.createSubLogger('sql', 'gray'); -const sqlMigrateLogger = sqlLogger.createSubLogger('migrate'); -const sqlSchemaLogger = sqlLogger.createSubLogger('schema'); - export type LoggerProps = { disableQueryTruncation?: boolean; enableQueryLogging?: boolean; @@ -118,16 +112,26 @@ function truncateSql(sql: string) { return sql.length > 100 ? `${sql.substring(0, 100)} [truncated]` : sql; } -function stringifyParameter(param: any) { +function stringifyParameter(param: unknown): string { if (param instanceof Date) { return param.toISOString(); } else { - return param; + return String(param); } } -class MyCustomLogger implements Logger { - constructor(private props: LoggerProps = {}) { +class TypeORMLogger implements Logger { + private readonly sqlLogger: MisskeyLogger; + private readonly sqlMigrateLogger: MisskeyLogger; + private readonly sqlSchemaLogger: MisskeyLogger; + + constructor( + private readonly props: LoggerProps = {}, + dbLogger: MisskeyLogger, + ) { + this.sqlLogger = dbLogger.createSubLogger('sql', 'gray'); + this.sqlLogger.createSubLogger('migrate'); + this.sqlLogger.createSubLogger('schema'); } @bindThis @@ -143,9 +147,9 @@ class MyCustomLogger implements Logger { } @bindThis - private transformParameters(parameters?: any[]) { + private transformParameters(parameters?: unknown[]): Data | undefined { if (this.props.enableQueryParamLogging && parameters && parameters.length > 0) { - return parameters.reduce((params, p, i) => { + return parameters.reduce((params: Record, p, i) => { params[`$${i + 1}`] = stringifyParameter(p); return params; }, {} as Record); @@ -155,37 +159,37 @@ class MyCustomLogger implements Logger { } @bindThis - public logQuery(query: string, parameters?: any[], queryRunner?: QueryRunner) { + public logQuery(query: string, parameters?: unknown[], queryRunner?: QueryRunner) { if (!this.props.enableQueryLogging) return; const prefix = (this.props.printReplicationMode && queryRunner) ? `[${queryRunner.getReplicationMode()}] ` : undefined; const transformed = this.transformQueryLog(query, { prefix }); - sqlLogger.debug(`Query run: ${transformed}`, this.transformParameters(parameters)); + this.sqlLogger.debug(`Query run: ${transformed}`, this.transformParameters(parameters)); } @bindThis - public logQueryError(error: string, query: string, parameters?: any[], queryRunner?: QueryRunner) { + public logQueryError(error: string, query: string, parameters?: unknown[], queryRunner?: QueryRunner) { const prefix = (this.props.printReplicationMode && queryRunner) ? `[${queryRunner.getReplicationMode()}] ` : undefined; const transformed = this.transformQueryLog(query, { prefix }); - sqlLogger.error(`Query error (${error}): ${transformed}`, this.transformParameters(parameters)); + this.sqlLogger.error(`Query error (${error}): ${transformed}`, this.transformParameters(parameters)); } @bindThis - public logQuerySlow(time: number, query: string, parameters?: any[], queryRunner?: QueryRunner) { + public logQuerySlow(time: number, query: string, parameters?: unknown[], queryRunner?: QueryRunner) { const prefix = (this.props.printReplicationMode && queryRunner) ? `[${queryRunner.getReplicationMode()}] ` : undefined; const transformed = this.transformQueryLog(query, { prefix }); - sqlLogger.warn(`Query is slow (${time}ms): ${transformed}`, this.transformParameters(parameters)); + this.sqlLogger.warn(`Query is slow (${time}ms): ${transformed}`, this.transformParameters(parameters)); } @bindThis public logSchemaBuild(message: string) { - sqlSchemaLogger.debug(message); + this.sqlSchemaLogger.debug(message); } @bindThis @@ -193,18 +197,18 @@ class MyCustomLogger implements Logger { switch (level) { case 'log': case 'info': { - sqlLogger.info(message); + this.sqlLogger.info(message); break; } case 'warn': { - sqlLogger.warn(message); + this.sqlLogger.warn(message); } } } @bindThis public logMigration(message: string) { - sqlMigrateLogger.debug(message); + this.sqlMigrateLogger.debug(message); } } @@ -294,7 +298,7 @@ export const entities = [ const log = process.env.NODE_ENV !== 'production'; -export function createPostgresDataSource(config: Config) { +export function createPostgresDataSource(config: Config, dbLogger: MisskeyLogger) { return new DataSource({ type: 'postgres', host: config.db.host, @@ -315,13 +319,13 @@ export function createPostgresDataSource(config: Config) { password: config.db.pass, database: config.db.db, }, - slaves: config.dbSlaves!.map(rep => ({ + slaves: config.dbSlaves?.map(rep => ({ host: rep.host, port: rep.port, username: rep.user, password: rep.pass, database: rep.db, - })), + })) ?? [], }, } : {}), synchronize: process.env.NODE_ENV === 'test', @@ -334,12 +338,12 @@ export function createPostgresDataSource(config: Config) { }, } : false, logging: log, - logger: new MyCustomLogger({ + logger: new TypeORMLogger({ disableQueryTruncation: config.logging?.sql?.disableQueryTruncation, enableQueryLogging: log, enableQueryParamLogging: config.logging?.sql?.enableQueryParamLogging, printReplicationMode: !!config.dbReplications, - }), + }, dbLogger), maxQueryExecutionTime: config.db.slowQueryThreshold, entities: entities, migrations: ['../../migration/*.js'],