inject DB logger through DI

This commit is contained in:
Hazelnoot 2025-10-02 14:05:34 -04:00
parent dd7545e105
commit 6c2206ab72
2 changed files with 37 additions and 32 deletions

View file

@ -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<string, string>, p, i) => {
params[`$${i + 1}`] = stringifyParameter(p);
return params;
}, {} as Record<string, string>);
@ -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'],