From 759b9f4cf133dfa6b06c6fcebf22aefc017363bd Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=E3=81=8A=E3=81=95=E3=82=80=E3=81=AE=E3=81=B2=E3=81=A8?=
 <46447427+samunohito@users.noreply.github.com>
Date: Tue, 14 Jan 2025 19:37:41 +0900
Subject: [PATCH] =?UTF-8?q?feat(backend):=20config(default.yml)=E3=81=8B?=
 =?UTF-8?q?=E3=82=89SQL=E3=83=AD=E3=82=B0=E5=85=A8=E6=96=87=E3=82=92?=
 =?UTF-8?q?=E5=87=BA=E5=8A=9B=E3=81=99=E3=82=8B=E3=81=8B=E5=90=A6=E3=81=8B?=
 =?UTF-8?q?=E3=82=92=E8=A8=AD=E5=AE=9A=E5=8F=AF=E8=83=BD=E3=81=AB=20(#1526?=
 =?UTF-8?q?8)?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

* feature(backend): config(default.yml)からSQLログ全文を出力するか否かを設定可能に

* disableHighlightやめる

* refactor
---
 .config/docker_example.yml       | 10 ++++++
 .config/example.yml              | 10 ++++++
 CHANGELOG.md                     |  1 +
 packages/backend/src/config.ts   | 14 ++++++++
 packages/backend/src/postgres.ts | 59 +++++++++++++++++++++++++++-----
 5 files changed, 86 insertions(+), 8 deletions(-)

diff --git a/.config/docker_example.yml b/.config/docker_example.yml
index 3f8e5734ce..0f5ba9696d 100644
--- a/.config/docker_example.yml
+++ b/.config/docker_example.yml
@@ -219,3 +219,13 @@ signToActivityPubGet: true
 
 # Upload or download file size limits (bytes)
 #maxFileSize: 262144000
+
+# Log settings
+# logging:
+#   sql:
+#     # Outputs query parameters during SQL execution to the log.
+#     # default: false
+#     enableQueryParamLogging: false
+#     # Disable query truncation. If set to true, the full text of the query will be output to the log.
+#     # default: false
+#     disableQueryTruncation: false
diff --git a/.config/example.yml b/.config/example.yml
index 60a6a0aa71..ea29cedd10 100644
--- a/.config/example.yml
+++ b/.config/example.yml
@@ -321,3 +321,13 @@ signToActivityPubGet: true
 
 # PID File of master process
 #pidFile: /tmp/misskey.pid
+
+# Log settings
+# logging:
+#   sql:
+#     # Outputs query parameters during SQL execution to the log.
+#     # default: false
+#     enableQueryParamLogging: false
+#     # Disable query truncation. If set to true, the full text of the query will be output to the log.
+#     # default: false
+#     disableQueryTruncation: false
diff --git a/CHANGELOG.md b/CHANGELOG.md
index b9f0d6495a..071cf22a5a 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -29,6 +29,7 @@
 - Enhance: pg_bigmが利用できるよう、ノートの検索をILIKE演算子でなくLIKE演算子でLOWER()をかけたテキストに対して行うように
 - Enhance: チャート更新時にDBに同時接続しないように  
   (Cherry-picked from https://activitypub.software/TransFem-org/Sharkey/-/merge_requests/830)
+- Enhance: config(default.yml)からSQLログ全文を出力するか否かを設定可能に ( #15266 )
 - Fix: ユーザーのプロフィール画面をアドレス入力などで直接表示した際に概要タブの描画に失敗する問題の修正( #15032 )
 - Fix: 起動前の疎通チェックが機能しなくなっていた問題を修正  
   (Cherry-picked from https://activitypub.software/TransFem-org/Sharkey/-/merge_requests/737)
diff --git a/packages/backend/src/config.ts b/packages/backend/src/config.ts
index 42f1033b9d..a5dc61db13 100644
--- a/packages/backend/src/config.ts
+++ b/packages/backend/src/config.ts
@@ -99,6 +99,13 @@ type Source = {
 	perUserNotificationsMaxCount?: number;
 	deactivateAntennaThreshold?: number;
 	pidFile: string;
+
+	logging?: {
+		sql?: {
+			disableQueryTruncation? : boolean,
+			enableQueryParamLogging? : boolean,
+		}
+	}
 };
 
 export type Config = {
@@ -151,6 +158,12 @@ export type Config = {
 	inboxJobMaxAttempts: number | undefined;
 	proxyRemoteFiles: boolean | undefined;
 	signToActivityPubGet: boolean | undefined;
+	logging?: {
+		sql?: {
+			disableQueryTruncation? : boolean,
+			enableQueryParamLogging? : boolean,
+		}
+	}
 
 	version: string;
 	publishTarballInsteadOfProvideRepositoryUrl: boolean;
@@ -293,6 +306,7 @@ export function loadConfig(): Config {
 		perUserNotificationsMaxCount: config.perUserNotificationsMaxCount ?? 500,
 		deactivateAntennaThreshold: config.deactivateAntennaThreshold ?? (1000 * 60 * 60 * 24 * 7),
 		pidFile: config.pidFile,
+		logging: config.logging,
 	};
 }
 
diff --git a/packages/backend/src/postgres.ts b/packages/backend/src/postgres.ts
index 251a03c303..d09240eba1 100644
--- a/packages/backend/src/postgres.ts
+++ b/packages/backend/src/postgres.ts
@@ -89,27 +89,65 @@ export const dbLogger = new MisskeyLogger('db');
 
 const sqlLogger = dbLogger.createSubLogger('sql', 'gray');
 
+export type LoggerProps = {
+	disableQueryTruncation?: boolean;
+	enableQueryParamLogging?: boolean;
+}
+
+function highlightSql(sql: string) {
+	return highlight.highlight(sql, {
+		language: 'sql', ignoreIllegals: true,
+	});
+}
+
+function truncateSql(sql: string) {
+	return sql.length > 100 ? `${sql.substring(0, 100)}...` : sql;
+}
+
+function stringifyParameter(param: any) {
+	if (param instanceof Date) {
+		return param.toISOString();
+	} else {
+		return param;
+	}
+}
+
 class MyCustomLogger implements Logger {
+	constructor(private props: LoggerProps = {}) {
+	}
+
 	@bindThis
-	private highlight(sql: string) {
-		return highlight.highlight(sql, {
-			language: 'sql', ignoreIllegals: true,
-		});
+	private transformQueryLog(sql: string) {
+		let modded = sql;
+		if (!this.props.disableQueryTruncation) {
+			modded = truncateSql(modded);
+		}
+
+		return highlightSql(modded);
+	}
+
+	@bindThis
+	private transformParameters(parameters?: any[]) {
+		if (this.props.enableQueryParamLogging && parameters && parameters.length > 0) {
+			return parameters.map(stringifyParameter);
+		}
+
+		return undefined;
 	}
 
 	@bindThis
 	public logQuery(query: string, parameters?: any[]) {
-		sqlLogger.info(this.highlight(query).substring(0, 100));
+		sqlLogger.info(this.transformQueryLog(query), this.transformParameters(parameters));
 	}
 
 	@bindThis
 	public logQueryError(error: string, query: string, parameters?: any[]) {
-		sqlLogger.error(this.highlight(query));
+		sqlLogger.error(this.transformQueryLog(query), this.transformParameters(parameters));
 	}
 
 	@bindThis
 	public logQuerySlow(time: number, query: string, parameters?: any[]) {
-		sqlLogger.warn(this.highlight(query));
+		sqlLogger.warn(this.transformQueryLog(query), this.transformParameters(parameters));
 	}
 
 	@bindThis
@@ -247,7 +285,12 @@ export function createPostgresDataSource(config: Config) {
 			},
 		} : false,
 		logging: log,
-		logger: log ? new MyCustomLogger() : undefined,
+		logger: log
+			? new MyCustomLogger({
+				disableQueryTruncation: config.logging?.sql?.disableQueryTruncation,
+				enableQueryParamLogging: config.logging?.sql?.enableQueryParamLogging,
+			})
+			: undefined,
 		maxQueryExecutionTime: 300,
 		entities: entities,
 		migrations: ['../../migration/*.js'],